]>
Commit | Line | Data |
---|---|---|
fef88f10 RK |
1 | /* |
2 | * Versatile Express Core Tile Cortex A9x4 Support | |
3 | */ | |
4 | #include <linux/init.h> | |
68aaae9e | 5 | #include <linux/gfp.h> |
fef88f10 RK |
6 | #include <linux/device.h> |
7 | #include <linux/dma-mapping.h> | |
f417cbad | 8 | #include <linux/platform_device.h> |
fef88f10 RK |
9 | #include <linux/amba/bus.h> |
10 | #include <linux/amba/clcd.h> | |
6d803ba7 | 11 | #include <linux/clkdev.h> |
fef88f10 | 12 | |
fef88f10 RK |
13 | #include <asm/hardware/arm_timer.h> |
14 | #include <asm/hardware/cache-l2x0.h> | |
15 | #include <asm/hardware/gic.h> | |
f417cbad | 16 | #include <asm/pmu.h> |
80b5efbd | 17 | #include <asm/smp_scu.h> |
bde28b84 | 18 | #include <asm/smp_twd.h> |
fef88f10 | 19 | |
fef88f10 RK |
20 | #include <mach/ct-ca9x4.h> |
21 | ||
8a9618f5 | 22 | #include <asm/hardware/timer-sp.h> |
fef88f10 | 23 | |
fef88f10 RK |
24 | #include <asm/mach/map.h> |
25 | #include <asm/mach/time.h> | |
26 | ||
27 | #include "core.h" | |
28 | ||
29 | #include <mach/motherboard.h> | |
30 | ||
0fb44b91 RK |
31 | #include <plat/clcd.h> |
32 | ||
fef88f10 RK |
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 | ||
54 | static void __init ct_ca9x4_map_io(void) | |
55 | { | |
e56c010f | 56 | #ifdef CONFIG_LOCAL_TIMERS |
bde28b84 | 57 | twd_base = MMIO_P2V(A9_MPCORE_TWD); |
e56c010f | 58 | #endif |
80b5efbd | 59 | iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc)); |
fef88f10 RK |
60 | } |
61 | ||
fef88f10 RK |
62 | static void __init ct_ca9x4_init_irq(void) |
63 | { | |
ff2e27ae RK |
64 | gic_init(0, 29, MMIO_P2V(A9_MPCORE_GIC_DIST), |
65 | MMIO_P2V(A9_MPCORE_GIC_CPU)); | |
fef88f10 RK |
66 | } |
67 | ||
68 | #if 0 | |
cdaf9a2f | 69 | static void __init ct_ca9x4_timer_init(void) |
fef88f10 RK |
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)); | |
75 | sp804_clockevents_init(MMIO_P2V(CT_CA9X4_TIMER0), IRQ_CT_CA9X4_TIMER0); | |
76 | } | |
77 | ||
78 | static struct sys_timer ct_ca9x4_timer = { | |
79 | .init = ct_ca9x4_timer_init, | |
80 | }; | |
81 | #endif | |
82 | ||
fef88f10 RK |
83 | static void ct_ca9x4_clcd_enable(struct clcd_fb *fb) |
84 | { | |
85 | v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1, 0); | |
86 | v2m_cfg_write(SYS_CFG_DVIMODE | SYS_CFG_SITE_DB1, 2); | |
87 | } | |
88 | ||
89 | static int ct_ca9x4_clcd_setup(struct clcd_fb *fb) | |
90 | { | |
91 | unsigned long framesize = 1024 * 768 * 2; | |
fef88f10 | 92 | |
0fb44b91 RK |
93 | fb->panel = versatile_clcd_get_panel("XVGA"); |
94 | if (!fb->panel) | |
95 | return -EINVAL; | |
fef88f10 | 96 | |
0fb44b91 | 97 | return versatile_clcd_setup_dma(fb, framesize); |
fef88f10 RK |
98 | } |
99 | ||
100 | static struct clcd_board ct_ca9x4_clcd_data = { | |
101 | .name = "CT-CA9X4", | |
0fb44b91 | 102 | .caps = CLCD_CAP_5551 | CLCD_CAP_565, |
fef88f10 RK |
103 | .check = clcdfb_check, |
104 | .decode = clcdfb_decode, | |
105 | .enable = ct_ca9x4_clcd_enable, | |
106 | .setup = ct_ca9x4_clcd_setup, | |
0fb44b91 RK |
107 | .mmap = versatile_clcd_mmap_dma, |
108 | .remove = versatile_clcd_remove_dma, | |
fef88f10 RK |
109 | }; |
110 | ||
111 | static AMBA_DEVICE(clcd, "ct:clcd", CT_CA9X4_CLCDC, &ct_ca9x4_clcd_data); | |
112 | static AMBA_DEVICE(dmc, "ct:dmc", CT_CA9X4_DMC, NULL); | |
113 | static AMBA_DEVICE(smc, "ct:smc", CT_CA9X4_SMC, NULL); | |
114 | static AMBA_DEVICE(gpio, "ct:gpio", CT_CA9X4_GPIO, NULL); | |
115 | ||
116 | static struct amba_device *ct_ca9x4_amba_devs[] __initdata = { | |
117 | &clcd_device, | |
118 | &dmc_device, | |
119 | &smc_device, | |
120 | &gpio_device, | |
121 | }; | |
122 | ||
123 | ||
124 | static long ct_round(struct clk *clk, unsigned long rate) | |
125 | { | |
126 | return rate; | |
127 | } | |
128 | ||
129 | static int ct_set(struct clk *clk, unsigned long rate) | |
130 | { | |
131 | return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_DB1 | 1, rate); | |
132 | } | |
133 | ||
134 | static const struct clk_ops osc1_clk_ops = { | |
135 | .round = ct_round, | |
136 | .set = ct_set, | |
137 | }; | |
138 | ||
139 | static struct clk osc1_clk = { | |
140 | .ops = &osc1_clk_ops, | |
141 | .rate = 24000000, | |
142 | }; | |
143 | ||
144 | static struct clk_lookup lookups[] = { | |
145 | { /* CLCD */ | |
146 | .dev_id = "ct:clcd", | |
147 | .clk = &osc1_clk, | |
148 | }, | |
149 | }; | |
150 | ||
f417cbad WD |
151 | static struct resource pmu_resources[] = { |
152 | [0] = { | |
153 | .start = IRQ_CT_CA9X4_PMU_CPU0, | |
154 | .end = IRQ_CT_CA9X4_PMU_CPU0, | |
155 | .flags = IORESOURCE_IRQ, | |
156 | }, | |
157 | [1] = { | |
158 | .start = IRQ_CT_CA9X4_PMU_CPU1, | |
159 | .end = IRQ_CT_CA9X4_PMU_CPU1, | |
160 | .flags = IORESOURCE_IRQ, | |
161 | }, | |
162 | [2] = { | |
163 | .start = IRQ_CT_CA9X4_PMU_CPU2, | |
164 | .end = IRQ_CT_CA9X4_PMU_CPU2, | |
165 | .flags = IORESOURCE_IRQ, | |
166 | }, | |
167 | [3] = { | |
168 | .start = IRQ_CT_CA9X4_PMU_CPU3, | |
169 | .end = IRQ_CT_CA9X4_PMU_CPU3, | |
170 | .flags = IORESOURCE_IRQ, | |
171 | }, | |
172 | }; | |
173 | ||
174 | static struct platform_device pmu_device = { | |
175 | .name = "arm-pmu", | |
176 | .id = ARM_PMU_DEVICE_CPU, | |
177 | .num_resources = ARRAY_SIZE(pmu_resources), | |
178 | .resource = pmu_resources, | |
179 | }; | |
180 | ||
493a451b RK |
181 | static void __init ct_ca9x4_init_early(void) |
182 | { | |
183 | clkdev_add_table(lookups, ARRAY_SIZE(lookups)); | |
493a451b RK |
184 | } |
185 | ||
cdaf9a2f | 186 | static void __init ct_ca9x4_init(void) |
fef88f10 RK |
187 | { |
188 | int i; | |
189 | ||
190 | #ifdef CONFIG_CACHE_L2X0 | |
2de59fea WD |
191 | void __iomem *l2x0_base = MMIO_P2V(CT_CA9X4_L2CC); |
192 | ||
193 | /* set RAM latencies to 1 cycle for this core tile. */ | |
194 | writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL); | |
195 | writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL); | |
196 | ||
197 | l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff); | |
fef88f10 RK |
198 | #endif |
199 | ||
fef88f10 RK |
200 | for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++) |
201 | amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource); | |
f417cbad WD |
202 | |
203 | platform_device_register(&pmu_device); | |
fef88f10 RK |
204 | } |
205 | ||
80b5efbd WD |
206 | #ifdef CONFIG_SMP |
207 | static void ct_ca9x4_init_cpu_map(void) | |
208 | { | |
209 | int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU)); | |
210 | ||
211 | for (i = 0; i < ncores; ++i) | |
212 | set_cpu_possible(i, true); | |
213 | } | |
214 | ||
215 | static void ct_ca9x4_smp_enable(unsigned int max_cpus) | |
216 | { | |
217 | int i; | |
218 | for (i = 0; i < max_cpus; i++) | |
219 | set_cpu_present(i, true); | |
220 | ||
221 | scu_enable(MMIO_P2V(A9_MPCORE_SCU)); | |
222 | } | |
223 | #endif | |
224 | ||
225 | struct ct_desc ct_ca9x4_desc __initdata = { | |
226 | .id = V2M_CT_ID_CA9, | |
227 | .name = "CA9x4", | |
fef88f10 | 228 | .map_io = ct_ca9x4_map_io, |
493a451b | 229 | .init_early = ct_ca9x4_init_early, |
80b5efbd WD |
230 | .init_irq = ct_ca9x4_init_irq, |
231 | .init_tile = ct_ca9x4_init, | |
232 | #ifdef CONFIG_SMP | |
233 | .init_cpu_map = ct_ca9x4_init_cpu_map, | |
234 | .smp_enable = ct_ca9x4_smp_enable, | |
fef88f10 | 235 | #endif |
80b5efbd | 236 | }; |