• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/arch/arm/plat-brcm/
1/*
2* ARM A9 MPCORE Platform base
3*/
4
5
6#include <linux/kernel.h>
7#include <linux/types.h>
8#include <linux/init.h>
9#include <linux/io.h>
10#include <linux/clk.h>
11#include <linux/errno.h>
12#include <linux/smp.h>
13#include <linux/clockchips.h>
14#include <linux/ioport.h>
15#include <linux/cpumask.h>
16
17#include <asm/mach/map.h>
18#include <asm/smp_twd.h>
19#include <asm/hardware/gic.h>
20
21#include <plat/mpcore.h>
22#include <mach/io_map.h>
23
24/* Globals */
25static void __iomem * periphbase ;
26extern void __iomem * twd_base;	/* declared in arch/arm/kernel/smp_twd.c */
27
28void __iomem * scu_base_addr(void)
29{
30	return (periphbase + MPCORE_SCU_OFF);
31}
32
33/*
34 * Local per-CPU timer support
35 * Called from arch/arm/kernel/smp.c
36 * Implemented in arch/arm/kernel/smp_twd.c
37 * All that is needed is to set the base address in mpcore_init() and irq here.
38 */
39void __cpuinit local_timer_setup(struct clock_event_device *evt)
40{
41        unsigned int cpu = smp_processor_id();
42
43	printk(KERN_INFO "MPCORE Private timer setup CPU%u\n", cpu);
44
45	evt->retries = 0;
46	evt->irq = MPCORE_IRQ_LOCALTIMER;
47	twd_timer_setup(evt);
48}
49
50void __init mpcore_map_io( void )
51{
52	struct map_desc desc ;
53	phys_addr_t base_addr;
54
55	/*
56	 * Cortex A9 Architecture Manual specifies this as a way to get
57	 * MPCORE PERHIPHBASE address at run-time
58	 */
59	asm( "mrc p15,4,%0,c15,c0,0 @ Read Configuration Base Address Register"
60		: "=&r" (base_addr) : : "cc" );
61
62	printk(KERN_INFO "MPCORE found at %p\n", (void *)base_addr);
63
64	/* Fix-map the entire PERIPHBASE 2*4K register block */
65	desc.virtual = MPCORE_BASE_VA;
66	desc.pfn = __phys_to_pfn( base_addr );
67	desc.length = SZ_8K;
68	desc.type = MT_DEVICE ;
69
70	iotable_init( &desc, 1);
71
72	periphbase = (void *) MPCORE_BASE_VA;
73
74	/* Local timer code needs just the register base address */
75	twd_base = periphbase + MPCORE_LTIMER_OFF;
76}
77
78void __init mpcore_init_gic( void )
79{
80	printk(KERN_INFO "MPCORE GIC init\n");
81
82	/* Init GIC interrupt distributor */
83	gic_dist_init( 0, periphbase + MPCORE_GIC_DIST_OFF, 1 );
84
85	/* Initialize the GIC CPU interface for the boot processor */
86	gic_cpu_init( 0, periphbase + MPCORE_GIC_CPUIF_OFF );
87
88}
89
90void __init mpcore_init_timer( unsigned long perphclk_freq )
91{
92
93	/* Init Global Timer */
94	mpcore_gtimer_init( periphbase + MPCORE_GTIMER_OFF,
95			perphclk_freq, MPCORE_IRQ_GLOBALTIMER );
96
97}
98
99
100/*
101 * For SMP - initialize GIC CPU interface for secondary cores
102 */
103void __cpuinit mpcore_cpu_init(void)
104{
105	/* Initialize the GIC CPU interface for the next processor */
106	gic_cpu_init( 0, periphbase + MPCORE_GIC_CPUIF_OFF );
107}
108