Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2b12b5c4 authored by Changhwan Youn's avatar Changhwan Youn Committed by Kukjin Kim
Browse files

ARM: S5PV310: Add new CPU initialization support



This patch adds Samsung S5PV310/S5PC210 CPU support.
The S5PV310/S5PC210 integrates a ARM Cortex A9 multi-core.

Signed-off-by: default avatarChanghwan Youn <chaos.youn@samsung.com>
Signed-off-by: default avatarJongpill Lee <boyko.lee@samsung.com>
Signed-off-by: default avatarJiseong Oh <jiseong.oh@samsung.com>
[kgene.kim@samsung.com: fix build errors]
Signed-off-by: default avatarKukjin Kim <kgene.kim@samsung.com>
parent 88baf209
Loading
Loading
Loading
Loading
+122 −0
Original line number Diff line number Diff line
/* linux/arch/arm/mach-s5pv310/cpu.c
 *
 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com/
 *
 * 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/sched.h>
#include <linux/sysdev.h>

#include <asm/mach/map.h>
#include <asm/mach/irq.h>

#include <asm/proc-fns.h>

#include <plat/cpu.h>
#include <plat/clock.h>
#include <plat/s5pv310.h>

#include <mach/regs-irq.h>

void __iomem *gic_cpu_base_addr;

extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
			 unsigned int irq_start);
extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);

/* Initial IO mappings */
static struct map_desc s5pv310_iodesc[] __initdata = {
	{
		.virtual	= (unsigned long)S5P_VA_COREPERI_BASE,
		.pfn		= __phys_to_pfn(S5PV310_PA_COREPERI),
		.length		= SZ_8K,
		.type		= MT_DEVICE,
	}, {
		.virtual	= (unsigned long)S5P_VA_COMBINER_BASE,
		.pfn		= __phys_to_pfn(S5PV310_PA_COMBINER),
		.length		= SZ_4K,
		.type		= MT_DEVICE,
	}, {
		.virtual	= (unsigned long)S5P_VA_L2CC,
		.pfn		= __phys_to_pfn(S5PV310_PA_L2CC),
		.length		= SZ_4K,
		.type		= MT_DEVICE,
	},
};

static void s5pv310_idle(void)
{
	if (!need_resched())
		cpu_do_idle();

	local_irq_enable();
}

/* s5pv310_map_io
 *
 * register the standard cpu IO areas
*/
void __init s5pv310_map_io(void)
{
	iotable_init(s5pv310_iodesc, ARRAY_SIZE(s5pv310_iodesc));
}

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

	s3c24xx_register_baseclocks(xtal);
	s5p_register_clocks(xtal);
	s5pv310_register_clocks();
	s5pv310_setup_clocks();
}

void __init s5pv310_init_irq(void)
{
	int irq;

	gic_cpu_base_addr = S5P_VA_GIC_CPU;
	gic_dist_init(0, S5P_VA_GIC_DIST, IRQ_LOCALTIMER);
	gic_cpu_init(0, 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 S5PV310
	 * uses GIC instead of VIC.
	 */
	s5p_init_irq(NULL, 0);
}

struct sysdev_class s5pv310_sysclass = {
	.name	= "s5pv310-core",
};

static struct sys_device s5pv310_sysdev = {
	.cls	= &s5pv310_sysclass,
};

static int __init s5pv310_core_init(void)
{
	return sysdev_class_register(&s5pv310_sysclass);
}

core_initcall(s5pv310_core_init);

int __init s5pv310_init(void)
{
	printk(KERN_INFO "S5PV310: Initializing architecture\n");

	/* set idle function */
	pm_idle = s5pv310_idle;

	return sysdev_register(&s5pv310_sysdev);
}
+41 −0
Original line number Diff line number Diff line
/*
 *  linux/arch/arm/mach-s5pv310/headsmp.S
 *
 *  Cloned from linux/arch/arm/mach-realview/headsmp.S
 *
 *  Copyright (c) 2003 ARM Limited
 *  All Rights Reserved
 *
 * 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/linkage.h>
#include <linux/init.h>

	__INIT

/*
 * s5pv310 specific entry point for secondary CPUs.  This provides
 * a "holding pen" into which all secondary cores are held until we're
 * ready for them to initialise.
 */
ENTRY(s5pv310_secondary_startup)
	mrc	p15, 0, r0, c0, c0, 5
	and	r0, r0, #15
	adr	r4, 1f
	ldmia	r4, {r5, r6}
	sub	r4, r4, r5
	add	r6, r6, r4
pen:	ldr	r7, [r6]
	cmp	r7, r0
	bne	pen

	/*
	 * we've been released from the holding pen: secondary_stack
	 * should now contain the SVC stack for this core
	 */
	b	secondary_startup

1:	.long	.
	.long	pen_release
+36 −0
Original line number Diff line number Diff line
/* linux/arch/arm/mach-s5pv310/include/mach/debug-macro.S
 *
 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com/
 *
 * Based on arch/arm/mach-s3c6400/include/mach/debug-macro.S
 *
 * 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.
*/

/* pull in the relevant register and map files. */

#include <mach/map.h>

	/* note, for the boot process to work we have to keep the UART
	 * virtual address aligned to an 1MiB boundary for the L1
	 * mapping the head code makes. We keep the UART virtual address
	 * aligned and add in the offset when we load the value here.
	 */

	.macro addruart, rx, tmp
		mrc	p15, 0, \rx, c1, c0
		tst	\rx, #1
		ldreq	\rx, = S3C_PA_UART
		ldrne	\rx, = S3C_VA_UART
#if CONFIG_DEBUG_S3C_UART != 0
		add	\rx, \rx, #(0x10000 * CONFIG_DEBUG_S3C_UART)
#endif
	.endm

#define fifo_full fifo_full_s5pv210
#define fifo_level fifo_level_s5pv210

#include <plat/debug-macro.S>
+84 −0
Original line number Diff line number Diff line
/* arch/arm/mach-s5pv310/include/mach/entry-macro.S
 *
 * Cloned from arch/arm/mach-realview/include/mach/entry-macro.S
 *
 * Low-level IRQ helper macros for S5PV310 platforms
 *
 * This file is licensed under  the terms of the GNU General Public
 * License version 2. This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
*/

#include <mach/hardware.h>
#include <asm/hardware/gic.h>

		.macro	disable_fiq
		.endm

		.macro  get_irqnr_preamble, base, tmp
		ldr	\base, =gic_cpu_base_addr
		ldr	\base, [\base]
		.endm

		.macro  arch_ret_to_user, tmp1, tmp2
		.endm

		/*
		 * The interrupt numbering scheme is defined in the
		 * interrupt controller spec.  To wit:
		 *
		 * Interrupts 0-15 are IPI
		 * 16-28 are reserved
		 * 29-31 are local.  We allow 30 to be used for the watchdog.
		 * 32-1020 are global
		 * 1021-1022 are reserved
		 * 1023 is "spurious" (no interrupt)
		 *
		 * For now, we ignore all local interrupts so only return an interrupt if it's
		 * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
		 *
		 * A simple read from the controller will tell us the number of the highest
                 * priority enabled interrupt.  We then just need to check whether it is in the
		 * valid range for an IRQ (30-1020 inclusive).
		 */

		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp

		ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */

		ldr	\tmp, =1021

		bic     \irqnr, \irqstat, #0x1c00

		cmp     \irqnr, #29
		cmpcc	\irqnr, \irqnr
		cmpne	\irqnr, \tmp
		cmpcs	\irqnr, \irqnr
		addne	\irqnr, \irqnr, #32

		.endm

		/* We assume that irqstat (the raw value of the IRQ acknowledge
		 * register) is preserved from the macro above.
		 * If there is an IPI, we immediately signal end of interrupt on the
		 * controller, since this requires the original irqstat value which
		 * we won't easily be able to recreate later.
		 */

		.macro test_for_ipi, irqnr, irqstat, base, tmp
		bic	\irqnr, \irqstat, #0x1c00
		cmp	\irqnr, #16
		strcc	\irqstat, [\base, #GIC_CPU_EOI]
		cmpcs	\irqnr, \irqnr
		.endm

		/* As above, this assumes that irqstat and base are preserved.. */

		.macro test_for_ltirq, irqnr, irqstat, base, tmp
		bic	\irqnr, \irqstat, #0x1c00
		mov	\tmp, #0
		cmp	\irqnr, #29
		moveq	\tmp, #1
		streq	\irqstat, [\base, #GIC_CPU_EOI]
		cmp	\tmp, #0
		.endm
+135 −0
Original line number Diff line number Diff line
/* linux/arch/arm/mach-s5pv310/include/mach/gpio.h
 *
 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com/
 *
 * S5PV310 - GPIO lib support
 *
 * 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.
*/

#ifndef __ASM_ARCH_GPIO_H
#define __ASM_ARCH_GPIO_H __FILE__

#define gpio_get_value	__gpio_get_value
#define gpio_set_value	__gpio_set_value
#define gpio_cansleep	__gpio_cansleep
#define gpio_to_irq	__gpio_to_irq

/* Practically, GPIO banks upto GPZ are the configurable gpio banks */

/* GPIO bank sizes */
#define S5PV310_GPIO_A0_NR	(8)
#define S5PV310_GPIO_A1_NR	(6)
#define S5PV310_GPIO_B_NR	(8)
#define S5PV310_GPIO_C0_NR	(5)
#define S5PV310_GPIO_C1_NR	(5)
#define S5PV310_GPIO_D0_NR	(4)
#define S5PV310_GPIO_D1_NR	(4)
#define S5PV310_GPIO_E0_NR	(5)
#define S5PV310_GPIO_E1_NR	(8)
#define S5PV310_GPIO_E2_NR	(6)
#define S5PV310_GPIO_E3_NR	(8)
#define S5PV310_GPIO_E4_NR	(8)
#define S5PV310_GPIO_F0_NR	(8)
#define S5PV310_GPIO_F1_NR	(8)
#define S5PV310_GPIO_F2_NR	(8)
#define S5PV310_GPIO_F3_NR	(6)
#define S5PV310_GPIO_J0_NR	(8)
#define S5PV310_GPIO_J1_NR	(5)
#define S5PV310_GPIO_K0_NR	(7)
#define S5PV310_GPIO_K1_NR	(7)
#define S5PV310_GPIO_K2_NR	(7)
#define S5PV310_GPIO_K3_NR	(7)
#define S5PV310_GPIO_L0_NR	(8)
#define S5PV310_GPIO_L1_NR	(3)
#define S5PV310_GPIO_L2_NR	(8)
#define S5PV310_GPIO_X0_NR	(8)
#define S5PV310_GPIO_X1_NR	(8)
#define S5PV310_GPIO_X2_NR	(8)
#define S5PV310_GPIO_X3_NR	(8)
#define S5PV310_GPIO_Z_NR	(7)

/* GPIO bank numbers */

#define S5PV310_GPIO_NEXT(__gpio) \
	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)

enum s5p_gpio_number {
	S5PV310_GPIO_A0_START	= 0,
	S5PV310_GPIO_A1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_A0),
	S5PV310_GPIO_B_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_A1),
	S5PV310_GPIO_C0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_B),
	S5PV310_GPIO_C1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_C0),
	S5PV310_GPIO_D0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_C1),
	S5PV310_GPIO_D1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_D0),
	S5PV310_GPIO_E0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_D1),
	S5PV310_GPIO_E1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E0),
	S5PV310_GPIO_E2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E1),
	S5PV310_GPIO_E3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E2),
	S5PV310_GPIO_E4_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E3),
	S5PV310_GPIO_F0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E4),
	S5PV310_GPIO_F1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F0),
	S5PV310_GPIO_F2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F1),
	S5PV310_GPIO_F3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F2),
	S5PV310_GPIO_J0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F3),
	S5PV310_GPIO_J1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_J0),
	S5PV310_GPIO_K0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_J1),
	S5PV310_GPIO_K1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K0),
	S5PV310_GPIO_K2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K1),
	S5PV310_GPIO_K3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K2),
	S5PV310_GPIO_L0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K3),
	S5PV310_GPIO_L1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_L0),
	S5PV310_GPIO_L2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_L1),
	S5PV310_GPIO_X0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_L2),
	S5PV310_GPIO_X1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X0),
	S5PV310_GPIO_X2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X1),
	S5PV310_GPIO_X3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X2),
	S5PV310_GPIO_Z_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X3),
};

/* S5PV310 GPIO number definitions */
#define S5PV310_GPA0(_nr)	(S5PV310_GPIO_A0_START + (_nr))
#define S5PV310_GPA1(_nr)	(S5PV310_GPIO_A1_START + (_nr))
#define S5PV310_GPB(_nr)	(S5PV310_GPIO_B_START + (_nr))
#define S5PV310_GPC0(_nr)	(S5PV310_GPIO_C0_START + (_nr))
#define S5PV310_GPC1(_nr)	(S5PV310_GPIO_C1_START + (_nr))
#define S5PV310_GPD0(_nr)	(S5PV310_GPIO_D0_START + (_nr))
#define S5PV310_GPD1(_nr)	(S5PV310_GPIO_D1_START + (_nr))
#define S5PV310_GPE0(_nr)	(S5PV310_GPIO_E0_START + (_nr))
#define S5PV310_GPE1(_nr)	(S5PV310_GPIO_E1_START + (_nr))
#define S5PV310_GPE2(_nr)	(S5PV310_GPIO_E2_START + (_nr))
#define S5PV310_GPE3(_nr)	(S5PV310_GPIO_E3_START + (_nr))
#define S5PV310_GPE4(_nr)	(S5PV310_GPIO_E4_START + (_nr))
#define S5PV310_GPF0(_nr)	(S5PV310_GPIO_F0_START + (_nr))
#define S5PV310_GPF1(_nr)	(S5PV310_GPIO_F1_START + (_nr))
#define S5PV310_GPF2(_nr)	(S5PV310_GPIO_F2_START + (_nr))
#define S5PV310_GPF3(_nr)	(S5PV310_GPIO_F3_START + (_nr))
#define S5PV310_GPJ0(_nr)	(S5PV310_GPIO_J0_START + (_nr))
#define S5PV310_GPJ1(_nr)	(S5PV310_GPIO_J1_START + (_nr))
#define S5PV310_GPK0(_nr)	(S5PV310_GPIO_K0_START + (_nr))
#define S5PV310_GPK1(_nr)	(S5PV310_GPIO_K1_START + (_nr))
#define S5PV310_GPK2(_nr)	(S5PV310_GPIO_K2_START + (_nr))
#define S5PV310_GPK3(_nr)	(S5PV310_GPIO_K3_START + (_nr))
#define S5PV310_GPL0(_nr)	(S5PV310_GPIO_L0_START + (_nr))
#define S5PV310_GPL1(_nr)	(S5PV310_GPIO_L1_START + (_nr))
#define S5PV310_GPL2(_nr)	(S5PV310_GPIO_L2_START + (_nr))
#define S5PV310_GPX0(_nr)	(S5PV310_GPIO_X0_START + (_nr))
#define S5PV310_GPX1(_nr)	(S5PV310_GPIO_X1_START + (_nr))
#define S5PV310_GPX2(_nr)	(S5PV310_GPIO_X2_START + (_nr))
#define S5PV310_GPX3(_nr)	(S5PV310_GPIO_X3_START + (_nr))
#define S5PV310_GPZ(_nr)	(S5PV310_GPIO_Z_START + (_nr))

/* the end of the S5PV310 specific gpios */
#define S5PV310_GPIO_END	(S5PV310_GPZ(S5PV310_GPIO_Z_NR) + 1)
#define S3C_GPIO_END		S5PV310_GPIO_END

/* define the number of gpios we need to the one after the GPZ() range */
#define ARCH_NR_GPIOS		(S5PV310_GPZ(S5PV310_GPIO_Z_NR) +	\
				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)

#include <asm-generic/gpio.h>

#endif /* __ASM_ARCH_GPIO_H */
Loading