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