linux/arch/arm/mach-exynos/common.c
Linus Torvalds dfc25e4503 ARM: SoC: cleanups for 3.15
These cleanup patches are mainly move stuff around and should all
 be harmless. They are mainly split out so that other branches can
 be based on top to avoid conflicts.
 
 Notable changes are:
 
 * We finally remove all mach/timex.h, after CLOCK_TICK_RATE is no
   longer used. (Uwe Kleine-König)
 * The Qualcomm MSM platform is split out into legacy mach-msm and
   new-style mach-qcom, to allow easier maintainance of the new
   hardware support without regressions. (Kumar Gala)
 * A rework of some of the Kconfig logic to simplify multiplatform
   support (Rob Herring)
 * Samsung Exynos gets closer to supporting multiplatform (Sachin
   Kamat and others)
 * mach-bcm3528 gets merged into mach-bcm (Stephen Warren)
 * at91 gains some common clock framework support (Alexandre Belloni,
   Jean-Jacques Hiblot and other French people).
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIVAwUAUz/yOWCrR//JCVInAQLOPBAAwTMkMrD8S8ggz6vfiQHZNdRPAC7NUJ46
 +eYKmBVi5d6EdnjNuRElWENsh0ZosSAUFHrXsIC2NdH9sAJ9HOqWNNLymuA59Jo9
 HZ/Ze6xQXDPNV7TROPoXuIli/2OCOXyyQHJsfI7h9V3PCx31qo0B5OdCxU0mtXK6
 r1giREhnJFwfQMF/FTdnzhalFJoSjWwv/nkpNmQDJKRLKj9GzwQqItqw68gV6RzU
 Gnt6YK+9xC1B0cfWTFhAm6kbr9i7mvHoMG5tE3no2uuJMn4K7TgeMqOyvPWhmUeB
 EZi656szT1m5VfRWOqG+7coZO2VM4GO4NI0Xfin3GHllugOYls1il/FAfCPMLiwh
 RvuOmQGCkLIpdkuHop5QaI/h1EzlHA59nzTjmGf1+wWPsm0CIg08XOD9izQbRnN9
 EmRqn1/8POIi17xcWyeMp8LB0APsTI+IflZFaYprEY9VlLLA/Pd+7udULhs8Bq8y
 1l6fB6aPZKnDKCBy/PEIR+y+EHFEbwfrx6zm/pxVDX6P5DlQMFWL78pdBoJUa2h8
 3pm/bSzNU5OSz1nJMLJv2jBTtnM5BvFgQBUi2qJ9Lr+nUhJXKCJ80kE/nOlXoCIU
 J952p3OhkYTQQcjuUVQeTXvRUOGB7mKok0pDFZNE6c7faqxTCudMABQq/KbMFstU
 eE3cH5FyYj4=
 =GcBb
 -----END PGP SIGNATURE-----

Merge tag 'cleanup-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull ARM SoC cleanups from Arnd Bergmann:
 "These cleanup patches are mainly move stuff around and should all be
  harmless.  They are mainly split out so that other branches can be
  based on top to avoid conflicts.

  Notable changes are:

   - We finally remove all mach/timex.h, after CLOCK_TICK_RATE is no
     longer used (Uwe Kleine-König)
   - The Qualcomm MSM platform is split out into legacy mach-msm and
     new-style mach-qcom, to allow easier maintainance of the new
     hardware support without regressions (Kumar Gala)
   - A rework of some of the Kconfig logic to simplify multiplatform
     support (Rob Herring)
   - Samsung Exynos gets closer to supporting multiplatform (Sachin
     Kamat and others)
   - mach-bcm3528 gets merged into mach-bcm (Stephen Warren)
   - at91 gains some common clock framework support (Alexandre Belloni,
     Jean-Jacques Hiblot and other French people)"

* tag 'cleanup-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (89 commits)
  ARM: hisi: select HAVE_ARM_SCU only for SMP
  ARM: efm32: allow uncompress debug output
  ARM: prima2: build reset code standalone
  ARM: at91: add PWM clock
  ARM: at91: move sam9261 SoC to common clk
  ARM: at91: prepare common clk transition for sam9261 SoC
  ARM: at91: updated the at91_dt_defconfig with support for the ADS7846
  ARM: at91: dt: sam9261: Device Tree support for the at91sam9261ek
  ARM: at91: dt: defconfig: Added the sam9261 to the list of DT-enabled SOCs
  ARM: at91: dt: Add at91sam9261 dt SoC support
  ARM: at91: switch sam9rl to common clock framework
  ARM: at91/dt: define main clk frequency of at91sam9rlek
  ARM: at91/dt: define at91sam9rl clocks
  ARM: at91: prepare common clk transition for sam9rl SoCs
  ARM: at91: prepare sam9 dt boards transition to common clk
  ARM: at91: dt: sam9rl: Device Tree for the at91sam9rlek
  ARM: at91/defconfig: Add the sam9rl to the list of DT-enabled SOCs
  ARM: at91: Add at91sam9rl DT SoC support
  ARM: at91: prepare at91sam9rl DT transition
  ARM: at91/defconfig: refresh at91sam9260_9g20_defconfig
  ...
2014-04-05 13:51:19 -07:00

421 lines
9.9 KiB
C

/*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Common Codes for EXYNOS
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <clocksource/samsung_pwm.h>
#include <linux/sched.h>
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/of_irq.h>
#include <linux/pm_domain.h>
#include <linux/export.h>
#include <linux/irqdomain.h>
#include <linux/of_address.h>
#include <linux/irqchip/arm-gic.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/platform_device.h>
#include <asm/proc-fns.h>
#include <asm/exception.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include <asm/cacheflush.h>
#include <plat/cpu.h>
#include <plat/pm.h>
#include "common.h"
#include "regs-pmu.h"
#define L2_AUX_VAL 0x7C470001
#define L2_AUX_MASK 0xC200ffff
static const char name_exynos4210[] = "EXYNOS4210";
static const char name_exynos4212[] = "EXYNOS4212";
static const char name_exynos4412[] = "EXYNOS4412";
static const char name_exynos5250[] = "EXYNOS5250";
static const char name_exynos5420[] = "EXYNOS5420";
static const char name_exynos5440[] = "EXYNOS5440";
static void exynos4_map_io(void);
static void exynos5_map_io(void);
static int exynos_init(void);
static struct cpu_table cpu_ids[] __initdata = {
{
.idcode = EXYNOS4210_CPU_ID,
.idmask = EXYNOS4_CPU_MASK,
.map_io = exynos4_map_io,
.init = exynos_init,
.name = name_exynos4210,
}, {
.idcode = EXYNOS4212_CPU_ID,
.idmask = EXYNOS4_CPU_MASK,
.map_io = exynos4_map_io,
.init = exynos_init,
.name = name_exynos4212,
}, {
.idcode = EXYNOS4412_CPU_ID,
.idmask = EXYNOS4_CPU_MASK,
.map_io = exynos4_map_io,
.init = exynos_init,
.name = name_exynos4412,
}, {
.idcode = EXYNOS5250_SOC_ID,
.idmask = EXYNOS5_SOC_MASK,
.map_io = exynos5_map_io,
.init = exynos_init,
.name = name_exynos5250,
}, {
.idcode = EXYNOS5420_SOC_ID,
.idmask = EXYNOS5_SOC_MASK,
.map_io = exynos5_map_io,
.init = exynos_init,
.name = name_exynos5420,
}, {
.idcode = EXYNOS5440_SOC_ID,
.idmask = EXYNOS5_SOC_MASK,
.init = exynos_init,
.name = name_exynos5440,
},
};
/* Initial IO mappings */
static struct map_desc exynos4_iodesc[] __initdata = {
{
.virtual = (unsigned long)S3C_VA_SYS,
.pfn = __phys_to_pfn(EXYNOS4_PA_SYSCON),
.length = SZ_64K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S3C_VA_TIMER,
.pfn = __phys_to_pfn(EXYNOS4_PA_TIMER),
.length = SZ_16K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S3C_VA_WATCHDOG,
.pfn = __phys_to_pfn(EXYNOS4_PA_WATCHDOG),
.length = SZ_4K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_SROMC,
.pfn = __phys_to_pfn(EXYNOS4_PA_SROMC),
.length = SZ_4K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_SYSTIMER,
.pfn = __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
.length = SZ_4K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_PMU,
.pfn = __phys_to_pfn(EXYNOS4_PA_PMU),
.length = SZ_64K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_COMBINER_BASE,
.pfn = __phys_to_pfn(EXYNOS4_PA_COMBINER),
.length = SZ_4K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_GIC_CPU,
.pfn = __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
.length = SZ_64K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_GIC_DIST,
.pfn = __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
.length = SZ_64K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_CMU,
.pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
.length = SZ_128K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_COREPERI_BASE,
.pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI),
.length = SZ_8K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_L2CC,
.pfn = __phys_to_pfn(EXYNOS4_PA_L2CC),
.length = SZ_4K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_DMC0,
.pfn = __phys_to_pfn(EXYNOS4_PA_DMC0),
.length = SZ_64K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_DMC1,
.pfn = __phys_to_pfn(EXYNOS4_PA_DMC1),
.length = SZ_64K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S3C_VA_USB_HSPHY,
.pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
.length = SZ_4K,
.type = MT_DEVICE,
},
};
static struct map_desc exynos4_iodesc0[] __initdata = {
{
.virtual = (unsigned long)S5P_VA_SYSRAM,
.pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
.length = SZ_4K,
.type = MT_DEVICE,
},
};
static struct map_desc exynos4_iodesc1[] __initdata = {
{
.virtual = (unsigned long)S5P_VA_SYSRAM,
.pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
.length = SZ_4K,
.type = MT_DEVICE,
},
};
static struct map_desc exynos4210_iodesc[] __initdata = {
{
.virtual = (unsigned long)S5P_VA_SYSRAM_NS,
.pfn = __phys_to_pfn(EXYNOS4210_PA_SYSRAM_NS),
.length = SZ_4K,
.type = MT_DEVICE,
},
};
static struct map_desc exynos4x12_iodesc[] __initdata = {
{
.virtual = (unsigned long)S5P_VA_SYSRAM_NS,
.pfn = __phys_to_pfn(EXYNOS4x12_PA_SYSRAM_NS),
.length = SZ_4K,
.type = MT_DEVICE,
},
};
static struct map_desc exynos5250_iodesc[] __initdata = {
{
.virtual = (unsigned long)S5P_VA_SYSRAM_NS,
.pfn = __phys_to_pfn(EXYNOS5250_PA_SYSRAM_NS),
.length = SZ_4K,
.type = MT_DEVICE,
},
};
static struct map_desc exynos5_iodesc[] __initdata = {
{
.virtual = (unsigned long)S3C_VA_SYS,
.pfn = __phys_to_pfn(EXYNOS5_PA_SYSCON),
.length = SZ_64K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S3C_VA_TIMER,
.pfn = __phys_to_pfn(EXYNOS5_PA_TIMER),
.length = SZ_16K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S3C_VA_WATCHDOG,
.pfn = __phys_to_pfn(EXYNOS5_PA_WATCHDOG),
.length = SZ_4K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_SROMC,
.pfn = __phys_to_pfn(EXYNOS5_PA_SROMC),
.length = SZ_4K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_SYSRAM,
.pfn = __phys_to_pfn(EXYNOS5_PA_SYSRAM),
.length = SZ_4K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_CMU,
.pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
.length = 144 * SZ_1K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_PMU,
.pfn = __phys_to_pfn(EXYNOS5_PA_PMU),
.length = SZ_64K,
.type = MT_DEVICE,
},
};
void exynos4_restart(enum reboot_mode mode, const char *cmd)
{
__raw_writel(0x1, S5P_SWRESET);
}
void exynos5_restart(enum reboot_mode mode, const char *cmd)
{
struct device_node *np;
u32 val;
void __iomem *addr;
val = 0x1;
addr = EXYNOS_SWRESET;
if (of_machine_is_compatible("samsung,exynos5440")) {
u32 status;
np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock");
addr = of_iomap(np, 0) + 0xbc;
status = __raw_readl(addr);
addr = of_iomap(np, 0) + 0xcc;
val = __raw_readl(addr);
val = (val & 0xffff0000) | (status & 0xffff);
}
__raw_writel(val, addr);
}
static struct platform_device exynos_cpuidle = {
.name = "exynos_cpuidle",
.id = -1,
};
void __init exynos_cpuidle_init(void)
{
platform_device_register(&exynos_cpuidle);
}
void __init exynos_cpufreq_init(void)
{
platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
}
void __init exynos_init_late(void)
{
if (of_machine_is_compatible("samsung,exynos5440"))
/* to be supported later */
return;
pm_genpd_poweroff_unused();
}
static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
int depth, void *data)
{
struct map_desc iodesc;
__be32 *reg;
unsigned long len;
if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") &&
!of_flat_dt_is_compatible(node, "samsung,exynos5440-clock"))
return 0;
reg = of_get_flat_dt_prop(node, "reg", &len);
if (reg == NULL || len != (sizeof(unsigned long) * 2))
return 0;
iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0]));
iodesc.length = be32_to_cpu(reg[1]) - 1;
iodesc.virtual = (unsigned long)S5P_VA_CHIPID;
iodesc.type = MT_DEVICE;
iotable_init(&iodesc, 1);
return 1;
}
/*
* exynos_map_io
*
* register the standard cpu IO areas
*/
void __init exynos_init_io(void)
{
debug_ll_io_init();
of_scan_flat_dt(exynos_fdt_map_chipid, NULL);
/* detect cpu id and rev. */
s5p_init_cpu(S5P_VA_CHIPID);
s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
}
static void __init exynos4_map_io(void)
{
iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_0)
iotable_init(exynos4_iodesc0, ARRAY_SIZE(exynos4_iodesc0));
else
iotable_init(exynos4_iodesc1, ARRAY_SIZE(exynos4_iodesc1));
if (soc_is_exynos4210())
iotable_init(exynos4210_iodesc, ARRAY_SIZE(exynos4210_iodesc));
if (soc_is_exynos4212() || soc_is_exynos4412())
iotable_init(exynos4x12_iodesc, ARRAY_SIZE(exynos4x12_iodesc));
}
static void __init exynos5_map_io(void)
{
iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
if (soc_is_exynos5250())
iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
}
struct bus_type exynos_subsys = {
.name = "exynos-core",
.dev_name = "exynos-core",
};
static struct device exynos4_dev = {
.bus = &exynos_subsys,
};
static int __init exynos_core_init(void)
{
return subsys_system_register(&exynos_subsys, NULL);
}
core_initcall(exynos_core_init);
static int __init exynos4_l2x0_cache_init(void)
{
int ret;
ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK);
if (ret)
return ret;
if (IS_ENABLED(CONFIG_S5P_SLEEP)) {
l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs);
clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long));
}
return 0;
}
early_initcall(exynos4_l2x0_cache_init);
static int __init exynos_init(void)
{
printk(KERN_INFO "EXYNOS: Initializing architecture\n");
return device_register(&exynos4_dev);
}