18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  Copyright (C) 1999,2000 Arm Limited
48c2ecf20Sopenharmony_ci *  Copyright (C) 2000 Deep Blue Solutions Ltd
58c2ecf20Sopenharmony_ci *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
68c2ecf20Sopenharmony_ci *  Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
78c2ecf20Sopenharmony_ci *    - add MX31 specific definitions
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/mm.h>
118c2ecf20Sopenharmony_ci#include <linux/init.h>
128c2ecf20Sopenharmony_ci#include <linux/err.h>
138c2ecf20Sopenharmony_ci#include <linux/io.h>
148c2ecf20Sopenharmony_ci#include <linux/of_address.h>
158c2ecf20Sopenharmony_ci#include <linux/pinctrl/machine.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <asm/system_misc.h>
188c2ecf20Sopenharmony_ci#include <asm/hardware/cache-l2x0.h>
198c2ecf20Sopenharmony_ci#include <asm/mach/map.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#include "common.h"
228c2ecf20Sopenharmony_ci#include "crmregs-imx3.h"
238c2ecf20Sopenharmony_ci#include "hardware.h"
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_civoid __iomem *mx3_ccm_base;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic void imx3_idle(void)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	unsigned long reg = 0;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	__asm__ __volatile__(
328c2ecf20Sopenharmony_ci		/* disable I and D cache */
338c2ecf20Sopenharmony_ci		"mrc p15, 0, %0, c1, c0, 0\n"
348c2ecf20Sopenharmony_ci		"bic %0, %0, #0x00001000\n"
358c2ecf20Sopenharmony_ci		"bic %0, %0, #0x00000004\n"
368c2ecf20Sopenharmony_ci		"mcr p15, 0, %0, c1, c0, 0\n"
378c2ecf20Sopenharmony_ci		/* invalidate I cache */
388c2ecf20Sopenharmony_ci		"mov %0, #0\n"
398c2ecf20Sopenharmony_ci		"mcr p15, 0, %0, c7, c5, 0\n"
408c2ecf20Sopenharmony_ci		/* clear and invalidate D cache */
418c2ecf20Sopenharmony_ci		"mov %0, #0\n"
428c2ecf20Sopenharmony_ci		"mcr p15, 0, %0, c7, c14, 0\n"
438c2ecf20Sopenharmony_ci		/* WFI */
448c2ecf20Sopenharmony_ci		"mov %0, #0\n"
458c2ecf20Sopenharmony_ci		"mcr p15, 0, %0, c7, c0, 4\n"
468c2ecf20Sopenharmony_ci		"nop\n" "nop\n" "nop\n" "nop\n"
478c2ecf20Sopenharmony_ci		"nop\n" "nop\n" "nop\n"
488c2ecf20Sopenharmony_ci		/* enable I and D cache */
498c2ecf20Sopenharmony_ci		"mrc p15, 0, %0, c1, c0, 0\n"
508c2ecf20Sopenharmony_ci		"orr %0, %0, #0x00001000\n"
518c2ecf20Sopenharmony_ci		"orr %0, %0, #0x00000004\n"
528c2ecf20Sopenharmony_ci		"mcr p15, 0, %0, c1, c0, 0\n"
538c2ecf20Sopenharmony_ci		: "=r" (reg));
548c2ecf20Sopenharmony_ci}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic void __iomem *imx3_ioremap_caller(phys_addr_t phys_addr, size_t size,
578c2ecf20Sopenharmony_ci					 unsigned int mtype, void *caller)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	if (mtype == MT_DEVICE) {
608c2ecf20Sopenharmony_ci		/*
618c2ecf20Sopenharmony_ci		 * Access all peripherals below 0x80000000 as nonshared device
628c2ecf20Sopenharmony_ci		 * on mx3, but leave l2cc alone.  Otherwise cache corruptions
638c2ecf20Sopenharmony_ci		 * can occur.
648c2ecf20Sopenharmony_ci		 */
658c2ecf20Sopenharmony_ci		if (phys_addr < 0x80000000 &&
668c2ecf20Sopenharmony_ci				!addr_in_module(phys_addr, MX3x_L2CC))
678c2ecf20Sopenharmony_ci			mtype = MT_DEVICE_NONSHARED;
688c2ecf20Sopenharmony_ci	}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	return __arm_ioremap_caller(phys_addr, size, mtype, caller);
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci#ifdef CONFIG_SOC_IMX31
748c2ecf20Sopenharmony_cistatic struct map_desc mx31_io_desc[] __initdata = {
758c2ecf20Sopenharmony_ci	imx_map_entry(MX31, X_MEMC, MT_DEVICE),
768c2ecf20Sopenharmony_ci	imx_map_entry(MX31, AVIC, MT_DEVICE_NONSHARED),
778c2ecf20Sopenharmony_ci	imx_map_entry(MX31, AIPS1, MT_DEVICE_NONSHARED),
788c2ecf20Sopenharmony_ci	imx_map_entry(MX31, AIPS2, MT_DEVICE_NONSHARED),
798c2ecf20Sopenharmony_ci	imx_map_entry(MX31, SPBA0, MT_DEVICE_NONSHARED),
808c2ecf20Sopenharmony_ci};
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci/*
838c2ecf20Sopenharmony_ci * This function initializes the memory map. It is called during the
848c2ecf20Sopenharmony_ci * system startup to create static physical to virtual memory mappings
858c2ecf20Sopenharmony_ci * for the IO modules.
868c2ecf20Sopenharmony_ci */
878c2ecf20Sopenharmony_civoid __init mx31_map_io(void)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
908c2ecf20Sopenharmony_ci}
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_cistatic void imx31_idle(void)
938c2ecf20Sopenharmony_ci{
948c2ecf20Sopenharmony_ci	int reg = imx_readl(mx3_ccm_base + MXC_CCM_CCMR);
958c2ecf20Sopenharmony_ci	reg &= ~MXC_CCM_CCMR_LPM_MASK;
968c2ecf20Sopenharmony_ci	imx_writel(reg, mx3_ccm_base + MXC_CCM_CCMR);
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	imx3_idle();
998c2ecf20Sopenharmony_ci}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_civoid __init imx31_init_early(void)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	struct device_node *np;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	mxc_set_cpu_type(MXC_CPU_MX31);
1068c2ecf20Sopenharmony_ci	arch_ioremap_caller = imx3_ioremap_caller;
1078c2ecf20Sopenharmony_ci	arm_pm_idle = imx31_idle;
1088c2ecf20Sopenharmony_ci	np = of_find_compatible_node(NULL, NULL, "fsl,imx31-ccm");
1098c2ecf20Sopenharmony_ci	mx3_ccm_base = of_iomap(np, 0);
1108c2ecf20Sopenharmony_ci	BUG_ON(!mx3_ccm_base);
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_civoid __init mx31_init_irq(void)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	void __iomem *avic_base;
1168c2ecf20Sopenharmony_ci	struct device_node *np;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	np = of_find_compatible_node(NULL, NULL, "fsl,imx31-avic");
1198c2ecf20Sopenharmony_ci	avic_base = of_iomap(np, 0);
1208c2ecf20Sopenharmony_ci	BUG_ON(!avic_base);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	mxc_init_irq(avic_base);
1238c2ecf20Sopenharmony_ci}
1248c2ecf20Sopenharmony_ci#endif /* ifdef CONFIG_SOC_IMX31 */
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci#ifdef CONFIG_SOC_IMX35
1278c2ecf20Sopenharmony_cistatic struct map_desc mx35_io_desc[] __initdata = {
1288c2ecf20Sopenharmony_ci	imx_map_entry(MX35, X_MEMC, MT_DEVICE),
1298c2ecf20Sopenharmony_ci	imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
1308c2ecf20Sopenharmony_ci	imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
1318c2ecf20Sopenharmony_ci	imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
1328c2ecf20Sopenharmony_ci	imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
1338c2ecf20Sopenharmony_ci};
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_civoid __init mx35_map_io(void)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistatic void imx35_idle(void)
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci	int reg = imx_readl(mx3_ccm_base + MXC_CCM_CCMR);
1438c2ecf20Sopenharmony_ci	reg &= ~MXC_CCM_CCMR_LPM_MASK;
1448c2ecf20Sopenharmony_ci	reg |= MXC_CCM_CCMR_LPM_WAIT_MX35;
1458c2ecf20Sopenharmony_ci	imx_writel(reg, mx3_ccm_base + MXC_CCM_CCMR);
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	imx3_idle();
1488c2ecf20Sopenharmony_ci}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_civoid __init imx35_init_early(void)
1518c2ecf20Sopenharmony_ci{
1528c2ecf20Sopenharmony_ci	struct device_node *np;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	mxc_set_cpu_type(MXC_CPU_MX35);
1558c2ecf20Sopenharmony_ci	arm_pm_idle = imx35_idle;
1568c2ecf20Sopenharmony_ci	arch_ioremap_caller = imx3_ioremap_caller;
1578c2ecf20Sopenharmony_ci	np = of_find_compatible_node(NULL, NULL, "fsl,imx35-ccm");
1588c2ecf20Sopenharmony_ci	mx3_ccm_base = of_iomap(np, 0);
1598c2ecf20Sopenharmony_ci	BUG_ON(!mx3_ccm_base);
1608c2ecf20Sopenharmony_ci}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_civoid __init mx35_init_irq(void)
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	void __iomem *avic_base;
1658c2ecf20Sopenharmony_ci	struct device_node *np;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	np = of_find_compatible_node(NULL, NULL, "fsl,imx35-avic");
1688c2ecf20Sopenharmony_ci	avic_base = of_iomap(np, 0);
1698c2ecf20Sopenharmony_ci	BUG_ON(!avic_base);
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	mxc_init_irq(avic_base);
1728c2ecf20Sopenharmony_ci}
1738c2ecf20Sopenharmony_ci#endif /* ifdef CONFIG_SOC_IMX35 */
174