Skip to content

Commit

Permalink
ARM: EXYNOS: add support for EXYNOS5250 SoC
Browse files Browse the repository at this point in the history
This patch add support for EXYNOS5250 SoC has two Cortex-A15 cores.
Since actually, most codes in mach-exynos/ are used commonly for
EXYNOS4 and EXYNOS5 the EXYNOS5/EXYNOS5250 has been implemented
in mach-exynos/.

Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
  • Loading branch information
Kukjin Kim committed Mar 14, 2012
1 parent 171c067 commit 94c7ca7
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 16 deletions.
1 change: 1 addition & 0 deletions arch/arm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ machine-$(CONFIG_ARCH_S5P64X0) := s5p64x0
machine-$(CONFIG_ARCH_S5PC100) := s5pc100
machine-$(CONFIG_ARCH_S5PV210) := s5pv210
machine-$(CONFIG_ARCH_EXYNOS4) := exynos
machine-$(CONFIG_ARCH_EXYNOS5) := exynos
machine-$(CONFIG_ARCH_SA1100) := sa1100
machine-$(CONFIG_ARCH_SHARK) := shark
machine-$(CONFIG_ARCH_SHMOBILE) := shmobile
Expand Down
191 changes: 179 additions & 12 deletions arch/arm/mach-exynos/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,12 @@
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 void exynos4_map_io(void);
static void exynos5_map_io(void);
static void exynos4_init_clocks(int xtal);
static void exynos5_init_clocks(int xtal);
static void exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no);
static int exynos_init(void);

Expand Down Expand Up @@ -80,6 +83,14 @@ static struct cpu_table cpu_ids[] __initdata = {
.init_uarts = exynos_init_uarts,
.init = exynos_init,
.name = name_exynos4412,
}, {
.idcode = EXYNOS5250_SOC_ID,
.idmask = EXYNOS5_SOC_MASK,
.map_io = exynos5_map_io,
.init_clocks = exynos5_init_clocks,
.init_uarts = exynos_init_uarts,
.init = exynos_init,
.name = name_exynos5250,
},
};

Expand All @@ -88,10 +99,14 @@ static struct cpu_table cpu_ids[] __initdata = {
static struct map_desc exynos_iodesc[] __initdata = {
{
.virtual = (unsigned long)S5P_VA_CHIPID,
.pfn = __phys_to_pfn(EXYNOS4_PA_CHIPID),
.pfn = __phys_to_pfn(EXYNOS_PA_CHIPID),
.length = SZ_4K,
.type = MT_DEVICE,
}, {
},
};

static struct map_desc exynos4_iodesc[] __initdata = {
{
.virtual = (unsigned long)S3C_VA_SYS,
.pfn = __phys_to_pfn(EXYNOS4_PA_SYSCON),
.length = SZ_64K,
Expand Down Expand Up @@ -141,11 +156,7 @@ static struct map_desc exynos_iodesc[] __initdata = {
.pfn = __phys_to_pfn(EXYNOS4_PA_UART),
.length = SZ_512K,
.type = MT_DEVICE,
},
};

static struct map_desc exynos4_iodesc[] __initdata = {
{
}, {
.virtual = (unsigned long)S5P_VA_CMU,
.pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
.length = SZ_128K,
Expand Down Expand Up @@ -206,11 +217,80 @@ static struct map_desc exynos4_iodesc1[] __initdata = {
},
};

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_SYSTIMER,
.pfn = __phys_to_pfn(EXYNOS5_PA_SYSTIMER),
.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,
}, {
.virtual = (unsigned long)S5P_VA_COMBINER_BASE,
.pfn = __phys_to_pfn(EXYNOS5_PA_COMBINER),
.length = SZ_4K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S3C_VA_UART,
.pfn = __phys_to_pfn(EXYNOS5_PA_UART),
.length = SZ_512K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_GIC_CPU,
.pfn = __phys_to_pfn(EXYNOS5_PA_GIC_CPU),
.length = SZ_64K,
.type = MT_DEVICE,
}, {
.virtual = (unsigned long)S5P_VA_GIC_DIST,
.pfn = __phys_to_pfn(EXYNOS5_PA_GIC_DIST),
.length = SZ_64K,
.type = MT_DEVICE,
},
};

void exynos4_restart(char mode, const char *cmd)
{
__raw_writel(0x1, S5P_SWRESET);
}

void exynos5_restart(char mode, const char *cmd)
{
__raw_writel(0x1, EXYNOS_SWRESET);
}

/*
* exynos_map_io
*
Expand Down Expand Up @@ -261,6 +341,16 @@ static void __init exynos4_map_io(void)
s5p_hdmi_setname("exynos4-hdmi");
}

static void __init exynos5_map_io(void)
{
iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));

/* The I2C bus controllers are directly compatible with s3c2440 */
s3c_i2c0_setname("s3c2440-i2c");
s3c_i2c1_setname("s3c2440-i2c");
s3c_i2c2_setname("s3c2440-i2c");
}

static void __init exynos4_init_clocks(int xtal)
{
printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
Expand All @@ -277,6 +367,17 @@ static void __init exynos4_init_clocks(int xtal)
exynos4_setup_clocks();
}

static void __init exynos5_init_clocks(int xtal)
{
printk(KERN_DEBUG "%s: initializing clocks\n", __func__);

s3c24xx_register_baseclocks(xtal);
s5p_register_clocks(xtal);

exynos5_register_clocks();
exynos5_setup_clocks();
}

#define COMBINER_ENABLE_SET 0x0
#define COMBINER_ENABLE_CLEAR 0x4
#define COMBINER_INT_STATUS 0xC
Expand Down Expand Up @@ -420,24 +521,59 @@ void __init exynos4_init_irq(void)
s5p_init_irq(NULL, 0);
}

void __init exynos5_init_irq(void)
{
int irq;

gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);

for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
COMBINER_IRQ(irq, 0));
combiner_cascade_irq(irq, IRQ_SPI(irq));
}

/*
* The parameters of s5p_init_irq() are for VIC init.
* Theses parameters should be NULL and 0 because EXYNOS4
* uses GIC instead of VIC.
*/
s5p_init_irq(NULL, 0);
}

struct bus_type exynos4_subsys = {
.name = "exynos4-core",
.dev_name = "exynos4-core",
};

struct bus_type exynos5_subsys = {
.name = "exynos5-core",
.dev_name = "exynos5-core",
};

static struct device exynos4_dev = {
.bus = &exynos4_subsys,
};

static int __init exynos4_core_init(void)
static struct device exynos5_dev = {
.bus = &exynos5_subsys,
};

static int __init exynos_core_init(void)
{
return subsys_system_register(&exynos4_subsys, NULL);
if (soc_is_exynos5250())
return subsys_system_register(&exynos5_subsys, NULL);
else
return subsys_system_register(&exynos4_subsys, NULL);
}
core_initcall(exynos4_core_init);
core_initcall(exynos_core_init);

#ifdef CONFIG_CACHE_L2X0
static int __init exynos4_l2x0_cache_init(void)
{
if (soc_is_exynos5250())
return 0;

/* TAG, Data Latency Control: 2cycle */
__raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);

Expand All @@ -457,14 +593,42 @@ static int __init exynos4_l2x0_cache_init(void)

return 0;
}

early_initcall(exynos4_l2x0_cache_init);
#endif

static int __init exynos5_l2_cache_init(void)
{
unsigned int val;

if (!soc_is_exynos5250())
return 0;

asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
"bic %0, %0, #(1 << 2)\n" /* cache disable */
"mcr p15, 0, %0, c1, c0, 0\n"
"mrc p15, 1, %0, c9, c0, 2\n"
: "=r"(val));

val |= (1 << 9) | (1 << 5) | (2 << 6) | (2 << 0);

asm volatile("mcr p15, 1, %0, c9, c0, 2\n" : : "r"(val));
asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
"orr %0, %0, #(1 << 2)\n" /* cache enable */
"mcr p15, 0, %0, c1, c0, 0\n"
: : "r"(val));

return 0;
}
early_initcall(exynos5_l2_cache_init);

static int __init exynos_init(void)
{
printk(KERN_INFO "EXYNOS: Initializing architecture\n");
return device_register(&exynos4_dev);

if (soc_is_exynos5250())
return device_register(&exynos5_dev);
else
return device_register(&exynos4_dev);
}

/* uart registration process */
Expand Down Expand Up @@ -673,6 +837,9 @@ static int __init exynos4_init_irq_eint(void)
{
int irq;

if (soc_is_exynos5250())
return 0;

for (irq = 0 ; irq <= 31 ; irq++) {
irq_set_chip_and_handler(IRQ_EINT(irq), &exynos4_irq_eint,
handle_level_irq);
Expand Down
11 changes: 11 additions & 0 deletions arch/arm/mach-exynos/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ extern struct sys_timer exynos4_timer;

void exynos_init_io(struct map_desc *mach_desc, int size);
void exynos4_init_irq(void);
void exynos5_init_irq(void);
void exynos4_restart(char mode, const char *cmd);
void exynos5_restart(char mode, const char *cmd);

#ifdef CONFIG_ARCH_EXYNOS4
void exynos4_register_clocks(void);
Expand All @@ -27,6 +29,15 @@ void exynos4_setup_clocks(void);
#define exynos4_setup_clocks()
#endif

#ifdef CONFIG_ARCH_EXYNOS5
void exynos5_register_clocks(void);
void exynos5_setup_clocks(void);

#else
#define exynos5_register_clocks()
#define exynos5_setup_clocks()
#endif

#ifdef CONFIG_CPU_EXYNOS4210
void exynos4210_register_clocks(void);

Expand Down
Loading

0 comments on commit 94c7ca7

Please sign in to comment.