2 * Versatile Express Core Tile Cortex A9x4 Support
4 #include <linux/init.h>
6 #include <linux/device.h>
7 #include <linux/dma-mapping.h>
8 #include <linux/platform_device.h>
9 #include <linux/amba/bus.h>
10 #include <linux/amba/clcd.h>
11 #include <linux/clkdev.h>
13 #include <asm/hardware/arm_timer.h>
14 #include <asm/hardware/cache-l2x0.h>
15 #include <asm/hardware/gic.h>
17 #include <asm/smp_scu.h>
18 #include <asm/smp_twd.h>
20 #include <mach/ct-ca9x4.h>
22 #include <asm/hardware/timer-sp.h>
24 #include <asm/mach/map.h>
25 #include <asm/mach/time.h>
29 #include <mach/motherboard.h>
31 #include <plat/clcd.h>
33 #define V2M_PA_CS7 0x10000000
35 static struct map_desc ct_ca9x4_io_desc
[] __initdata
= {
37 .virtual = __MMIO_P2V(CT_CA9X4_MPIC
),
38 .pfn
= __phys_to_pfn(CT_CA9X4_MPIC
),
42 .virtual = __MMIO_P2V(CT_CA9X4_SP804_TIMER
),
43 .pfn
= __phys_to_pfn(CT_CA9X4_SP804_TIMER
),
47 .virtual = __MMIO_P2V(CT_CA9X4_L2CC
),
48 .pfn
= __phys_to_pfn(CT_CA9X4_L2CC
),
54 static void __init
ct_ca9x4_map_io(void)
56 #ifdef CONFIG_LOCAL_TIMERS
57 twd_base
= MMIO_P2V(A9_MPCORE_TWD
);
59 iotable_init(ct_ca9x4_io_desc
, ARRAY_SIZE(ct_ca9x4_io_desc
));
62 static void __init
ct_ca9x4_init_irq(void)
64 gic_init(0, 29, MMIO_P2V(A9_MPCORE_GIC_DIST
),
65 MMIO_P2V(A9_MPCORE_GIC_CPU
));
69 static void __init
ct_ca9x4_timer_init(void)
71 writel(0, MMIO_P2V(CT_CA9X4_TIMER0
) + TIMER_CTRL
);
72 writel(0, MMIO_P2V(CT_CA9X4_TIMER1
) + TIMER_CTRL
);
74 sp804_clocksource_init(MMIO_P2V(CT_CA9X4_TIMER1
), "ct-timer1");
75 sp804_clockevents_init(MMIO_P2V(CT_CA9X4_TIMER0
), IRQ_CT_CA9X4_TIMER0
,
79 static struct sys_timer ct_ca9x4_timer
= {
80 .init
= ct_ca9x4_timer_init
,
84 static void ct_ca9x4_clcd_enable(struct clcd_fb
*fb
)
86 v2m_cfg_write(SYS_CFG_MUXFPGA
| SYS_CFG_SITE_DB1
, 0);
87 v2m_cfg_write(SYS_CFG_DVIMODE
| SYS_CFG_SITE_DB1
, 2);
90 static int ct_ca9x4_clcd_setup(struct clcd_fb
*fb
)
92 unsigned long framesize
= 1024 * 768 * 2;
94 fb
->panel
= versatile_clcd_get_panel("XVGA");
98 return versatile_clcd_setup_dma(fb
, framesize
);
101 static struct clcd_board ct_ca9x4_clcd_data
= {
103 .caps
= CLCD_CAP_5551
| CLCD_CAP_565
,
104 .check
= clcdfb_check
,
105 .decode
= clcdfb_decode
,
106 .enable
= ct_ca9x4_clcd_enable
,
107 .setup
= ct_ca9x4_clcd_setup
,
108 .mmap
= versatile_clcd_mmap_dma
,
109 .remove
= versatile_clcd_remove_dma
,
112 static AMBA_DEVICE(clcd
, "ct:clcd", CT_CA9X4_CLCDC
, &ct_ca9x4_clcd_data
);
113 static AMBA_DEVICE(dmc
, "ct:dmc", CT_CA9X4_DMC
, NULL
);
114 static AMBA_DEVICE(smc
, "ct:smc", CT_CA9X4_SMC
, NULL
);
115 static AMBA_DEVICE(gpio
, "ct:gpio", CT_CA9X4_GPIO
, NULL
);
117 static struct amba_device
*ct_ca9x4_amba_devs
[] __initdata
= {
125 static long ct_round(struct clk
*clk
, unsigned long rate
)
130 static int ct_set(struct clk
*clk
, unsigned long rate
)
132 return v2m_cfg_write(SYS_CFG_OSC
| SYS_CFG_SITE_DB1
| 1, rate
);
135 static const struct clk_ops osc1_clk_ops
= {
140 static struct clk osc1_clk
= {
141 .ops
= &osc1_clk_ops
,
145 static struct clk ct_sp804_clk
= {
149 static struct clk_lookup lookups
[] = {
153 }, { /* SP804 timers */
155 .con_id
= "ct-timer0",
156 .clk
= &ct_sp804_clk
,
157 }, { /* SP804 timers */
159 .con_id
= "ct-timer1",
160 .clk
= &ct_sp804_clk
,
164 static struct resource pmu_resources
[] = {
166 .start
= IRQ_CT_CA9X4_PMU_CPU0
,
167 .end
= IRQ_CT_CA9X4_PMU_CPU0
,
168 .flags
= IORESOURCE_IRQ
,
171 .start
= IRQ_CT_CA9X4_PMU_CPU1
,
172 .end
= IRQ_CT_CA9X4_PMU_CPU1
,
173 .flags
= IORESOURCE_IRQ
,
176 .start
= IRQ_CT_CA9X4_PMU_CPU2
,
177 .end
= IRQ_CT_CA9X4_PMU_CPU2
,
178 .flags
= IORESOURCE_IRQ
,
181 .start
= IRQ_CT_CA9X4_PMU_CPU3
,
182 .end
= IRQ_CT_CA9X4_PMU_CPU3
,
183 .flags
= IORESOURCE_IRQ
,
187 static struct platform_device pmu_device
= {
189 .id
= ARM_PMU_DEVICE_CPU
,
190 .num_resources
= ARRAY_SIZE(pmu_resources
),
191 .resource
= pmu_resources
,
194 static void __init
ct_ca9x4_init_early(void)
196 clkdev_add_table(lookups
, ARRAY_SIZE(lookups
));
199 static void __init
ct_ca9x4_init(void)
203 #ifdef CONFIG_CACHE_L2X0
204 void __iomem
*l2x0_base
= MMIO_P2V(CT_CA9X4_L2CC
);
206 /* set RAM latencies to 1 cycle for this core tile. */
207 writel(0, l2x0_base
+ L2X0_TAG_LATENCY_CTRL
);
208 writel(0, l2x0_base
+ L2X0_DATA_LATENCY_CTRL
);
210 l2x0_init(l2x0_base
, 0x00400000, 0xfe0fffff);
213 for (i
= 0; i
< ARRAY_SIZE(ct_ca9x4_amba_devs
); i
++)
214 amba_device_register(ct_ca9x4_amba_devs
[i
], &iomem_resource
);
216 platform_device_register(&pmu_device
);
220 static void ct_ca9x4_init_cpu_map(void)
222 int i
, ncores
= scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU
));
224 if (ncores
> nr_cpu_ids
) {
225 pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
230 for (i
= 0; i
< ncores
; ++i
)
231 set_cpu_possible(i
, true);
233 set_smp_cross_call(gic_raise_softirq
);
236 static void ct_ca9x4_smp_enable(unsigned int max_cpus
)
238 scu_enable(MMIO_P2V(A9_MPCORE_SCU
));
242 struct ct_desc ct_ca9x4_desc __initdata
= {
245 .map_io
= ct_ca9x4_map_io
,
246 .init_early
= ct_ca9x4_init_early
,
247 .init_irq
= ct_ca9x4_init_irq
,
248 .init_tile
= ct_ca9x4_init
,
250 .init_cpu_map
= ct_ca9x4_init_cpu_map
,
251 .smp_enable
= ct_ca9x4_smp_enable
,