1 /*
2  * Versatile Express Core Tile Cortex A9x4 Support
3  */
4 #include <linux/init.h>
5 #include <linux/gfp.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>
12 
13 #include <asm/hardware/arm_timer.h>
14 #include <asm/hardware/cache-l2x0.h>
15 #include <asm/hardware/gic.h>
16 #include <asm/pmu.h>
17 #include <asm/smp_scu.h>
18 #include <asm/smp_twd.h>
19 
20 #include <mach/ct-ca9x4.h>
21 
22 #include <asm/hardware/timer-sp.h>
23 
24 #include <asm/mach/map.h>
25 #include <asm/mach/time.h>
26 
27 #include "core.h"
28 
29 #include <mach/motherboard.h>
30 
31 #include <plat/clcd.h>
32 
33 #define V2M_PA_CS7	0x10000000
34 
35 static struct map_desc ct_ca9x4_io_desc[] __initdata = {
36 	{
37 		.virtual	= __MMIO_P2V(CT_CA9X4_MPIC),
38 		.pfn		= __phys_to_pfn(CT_CA9X4_MPIC),
39 		.length		= SZ_16K,
40 		.type		= MT_DEVICE,
41 	}, {
42 		.virtual	= __MMIO_P2V(CT_CA9X4_SP804_TIMER),
43 		.pfn		= __phys_to_pfn(CT_CA9X4_SP804_TIMER),
44 		.length		= SZ_4K,
45 		.type		= MT_DEVICE,
46 	}, {
47 		.virtual	= __MMIO_P2V(CT_CA9X4_L2CC),
48 		.pfn		= __phys_to_pfn(CT_CA9X4_L2CC),
49 		.length		= SZ_4K,
50 		.type		= MT_DEVICE,
51 	},
52 };
53 
ct_ca9x4_map_io(void)54 static void __init ct_ca9x4_map_io(void)
55 {
56 #ifdef CONFIG_LOCAL_TIMERS
57 	twd_base = MMIO_P2V(A9_MPCORE_TWD);
58 #endif
59 	iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
60 }
61 
ct_ca9x4_init_irq(void)62 static void __init ct_ca9x4_init_irq(void)
63 {
64 	gic_init(0, 29, MMIO_P2V(A9_MPCORE_GIC_DIST),
65 		 MMIO_P2V(A9_MPCORE_GIC_CPU));
66 }
67 
68 #if 0
69 static void __init ct_ca9x4_timer_init(void)
70 {
71 	writel(0, MMIO_P2V(CT_CA9X4_TIMER0) + TIMER_CTRL);
72 	writel(0, MMIO_P2V(CT_CA9X4_TIMER1) + TIMER_CTRL);
73 
74 	sp804_clocksource_init(MMIO_P2V(CT_CA9X4_TIMER1), "ct-timer1");
75 	sp804_clockevents_init(MMIO_P2V(CT_CA9X4_TIMER0), IRQ_CT_CA9X4_TIMER0,
76 		"ct-timer0");
77 }
78 
79 static struct sys_timer ct_ca9x4_timer = {
80 	.init	= ct_ca9x4_timer_init,
81 };
82 #endif
83 
ct_ca9x4_clcd_enable(struct clcd_fb * fb)84 static void ct_ca9x4_clcd_enable(struct clcd_fb *fb)
85 {
86 	v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1, 0);
87 	v2m_cfg_write(SYS_CFG_DVIMODE | SYS_CFG_SITE_DB1, 2);
88 }
89 
ct_ca9x4_clcd_setup(struct clcd_fb * fb)90 static int ct_ca9x4_clcd_setup(struct clcd_fb *fb)
91 {
92 	unsigned long framesize = 1024 * 768 * 2;
93 
94 	fb->panel = versatile_clcd_get_panel("XVGA");
95 	if (!fb->panel)
96 		return -EINVAL;
97 
98 	return versatile_clcd_setup_dma(fb, framesize);
99 }
100 
101 static struct clcd_board ct_ca9x4_clcd_data = {
102 	.name		= "CT-CA9X4",
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,
110 };
111 
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);
116 
117 static struct amba_device *ct_ca9x4_amba_devs[] __initdata = {
118 	&clcd_device,
119 	&dmc_device,
120 	&smc_device,
121 	&gpio_device,
122 };
123 
124 
ct_round(struct clk * clk,unsigned long rate)125 static long ct_round(struct clk *clk, unsigned long rate)
126 {
127 	return rate;
128 }
129 
ct_set(struct clk * clk,unsigned long rate)130 static int ct_set(struct clk *clk, unsigned long rate)
131 {
132 	return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_DB1 | 1, rate);
133 }
134 
135 static const struct clk_ops osc1_clk_ops = {
136 	.round	= ct_round,
137 	.set	= ct_set,
138 };
139 
140 static struct clk osc1_clk = {
141 	.ops	= &osc1_clk_ops,
142 	.rate	= 24000000,
143 };
144 
145 static struct clk ct_sp804_clk = {
146 	.rate	= 1000000,
147 };
148 
149 static struct clk_lookup lookups[] = {
150 	{	/* CLCD */
151 		.dev_id		= "ct:clcd",
152 		.clk		= &osc1_clk,
153 	}, {	/* SP804 timers */
154 		.dev_id		= "sp804",
155 		.con_id		= "ct-timer0",
156 		.clk		= &ct_sp804_clk,
157 	}, {	/* SP804 timers */
158 		.dev_id		= "sp804",
159 		.con_id		= "ct-timer1",
160 		.clk		= &ct_sp804_clk,
161 	},
162 };
163 
164 static struct resource pmu_resources[] = {
165 	[0] = {
166 		.start	= IRQ_CT_CA9X4_PMU_CPU0,
167 		.end	= IRQ_CT_CA9X4_PMU_CPU0,
168 		.flags	= IORESOURCE_IRQ,
169 	},
170 	[1] = {
171 		.start	= IRQ_CT_CA9X4_PMU_CPU1,
172 		.end	= IRQ_CT_CA9X4_PMU_CPU1,
173 		.flags	= IORESOURCE_IRQ,
174 	},
175 	[2] = {
176 		.start	= IRQ_CT_CA9X4_PMU_CPU2,
177 		.end	= IRQ_CT_CA9X4_PMU_CPU2,
178 		.flags	= IORESOURCE_IRQ,
179 	},
180 	[3] = {
181 		.start	= IRQ_CT_CA9X4_PMU_CPU3,
182 		.end	= IRQ_CT_CA9X4_PMU_CPU3,
183 		.flags	= IORESOURCE_IRQ,
184 	},
185 };
186 
187 static struct platform_device pmu_device = {
188 	.name		= "arm-pmu",
189 	.id		= ARM_PMU_DEVICE_CPU,
190 	.num_resources	= ARRAY_SIZE(pmu_resources),
191 	.resource	= pmu_resources,
192 };
193 
ct_ca9x4_init_early(void)194 static void __init ct_ca9x4_init_early(void)
195 {
196 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
197 }
198 
ct_ca9x4_init(void)199 static void __init ct_ca9x4_init(void)
200 {
201 	int i;
202 
203 #ifdef CONFIG_CACHE_L2X0
204 	void __iomem *l2x0_base = MMIO_P2V(CT_CA9X4_L2CC);
205 
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);
209 
210 	l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff);
211 #endif
212 
213 	for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++)
214 		amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource);
215 
216 	platform_device_register(&pmu_device);
217 }
218 
219 #ifdef CONFIG_SMP
ct_ca9x4_init_cpu_map(void)220 static void __init ct_ca9x4_init_cpu_map(void)
221 {
222 	int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU));
223 
224 	if (ncores > nr_cpu_ids) {
225 		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
226 			ncores, nr_cpu_ids);
227 		ncores = nr_cpu_ids;
228 	}
229 
230 	for (i = 0; i < ncores; ++i)
231 		set_cpu_possible(i, true);
232 
233 	set_smp_cross_call(gic_raise_softirq);
234 }
235 
ct_ca9x4_smp_enable(unsigned int max_cpus)236 static void __init ct_ca9x4_smp_enable(unsigned int max_cpus)
237 {
238 	scu_enable(MMIO_P2V(A9_MPCORE_SCU));
239 }
240 #endif
241 
242 struct ct_desc ct_ca9x4_desc __initdata = {
243 	.id		= V2M_CT_ID_CA9,
244 	.name		= "CA9x4",
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,
249 #ifdef CONFIG_SMP
250 	.init_cpu_map	= ct_ca9x4_init_cpu_map,
251 	.smp_enable	= ct_ca9x4_smp_enable,
252 #endif
253 };
254