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 12#include <asm/clkdev.h> 13#include <asm/pgtable.h> 14#include <asm/hardware/arm_timer.h> 15#include <asm/hardware/cache-l2x0.h> 16#include <asm/hardware/gic.h> 17#include <asm/mach-types.h> 18#include <asm/pmu.h> 19#include <asm/smp_twd.h> 20 21#include <mach/clkdev.h> 22#include <mach/ct-ca9x4.h> 23 24#include <plat/timer-sp.h> 25 26#include <asm/mach/arch.h> 27#include <asm/mach/map.h> 28#include <asm/mach/time.h> 29 30#include "core.h" 31 32#include <mach/motherboard.h> 33 34#define V2M_PA_CS7 0x10000000 35 36static struct map_desc ct_ca9x4_io_desc[] __initdata = { 37 { 38 .virtual = __MMIO_P2V(CT_CA9X4_MPIC), 39 .pfn = __phys_to_pfn(CT_CA9X4_MPIC), 40 .length = SZ_16K, 41 .type = MT_DEVICE, 42 }, { 43 .virtual = __MMIO_P2V(CT_CA9X4_SP804_TIMER), 44 .pfn = __phys_to_pfn(CT_CA9X4_SP804_TIMER), 45 .length = SZ_4K, 46 .type = MT_DEVICE, 47 }, { 48 .virtual = __MMIO_P2V(CT_CA9X4_L2CC), 49 .pfn = __phys_to_pfn(CT_CA9X4_L2CC), 50 .length = SZ_4K, 51 .type = MT_DEVICE, 52 }, 53}; 54 55static void __init ct_ca9x4_map_io(void) 56{ 57 twd_base = MMIO_P2V(A9_MPCORE_TWD); 58 v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc)); 59} 60 61void __iomem *gic_cpu_base_addr; 62 63static void __init ct_ca9x4_init_irq(void) 64{ 65 gic_cpu_base_addr = MMIO_P2V(A9_MPCORE_GIC_CPU); 66 gic_dist_init(0, MMIO_P2V(A9_MPCORE_GIC_DIST), 29); 67 gic_cpu_init(0, gic_cpu_base_addr); 68} 69 70 71static struct clcd_panel xvga_panel = { 72 .mode = { 73 .name = "XVGA", 74 .refresh = 60, 75 .xres = 1024, 76 .yres = 768, 77 .pixclock = 15384, 78 .left_margin = 168, 79 .right_margin = 8, 80 .upper_margin = 29, 81 .lower_margin = 3, 82 .hsync_len = 144, 83 .vsync_len = 6, 84 .sync = 0, 85 .vmode = FB_VMODE_NONINTERLACED, 86 }, 87 .width = -1, 88 .height = -1, 89 .tim2 = TIM2_BCD | TIM2_IPC, 90 .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), 91 .bpp = 16, 92}; 93 94static void ct_ca9x4_clcd_enable(struct clcd_fb *fb) 95{ 96 v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1, 0); 97 v2m_cfg_write(SYS_CFG_DVIMODE | SYS_CFG_SITE_DB1, 2); 98} 99 100static int ct_ca9x4_clcd_setup(struct clcd_fb *fb) 101{ 102 unsigned long framesize = 1024 * 768 * 2; 103 dma_addr_t dma; 104 105 fb->panel = &xvga_panel; 106 107 fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize, 108 &dma, GFP_KERNEL); 109 if (!fb->fb.screen_base) { 110 printk(KERN_ERR "CLCD: unable to map frame buffer\n"); 111 return -ENOMEM; 112 } 113 fb->fb.fix.smem_start = dma; 114 fb->fb.fix.smem_len = framesize; 115 116 return 0; 117} 118 119static int ct_ca9x4_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) 120{ 121 return dma_mmap_writecombine(&fb->dev->dev, vma, fb->fb.screen_base, 122 fb->fb.fix.smem_start, fb->fb.fix.smem_len); 123} 124 125static void ct_ca9x4_clcd_remove(struct clcd_fb *fb) 126{ 127 dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, 128 fb->fb.screen_base, fb->fb.fix.smem_start); 129} 130 131static struct clcd_board ct_ca9x4_clcd_data = { 132 .name = "CT-CA9X4", 133 .check = clcdfb_check, 134 .decode = clcdfb_decode, 135 .enable = ct_ca9x4_clcd_enable, 136 .setup = ct_ca9x4_clcd_setup, 137 .mmap = ct_ca9x4_clcd_mmap, 138 .remove = ct_ca9x4_clcd_remove, 139}; 140 141static AMBA_DEVICE(clcd, "ct:clcd", CT_CA9X4_CLCDC, &ct_ca9x4_clcd_data); 142static AMBA_DEVICE(dmc, "ct:dmc", CT_CA9X4_DMC, NULL); 143static AMBA_DEVICE(smc, "ct:smc", CT_CA9X4_SMC, NULL); 144static AMBA_DEVICE(gpio, "ct:gpio", CT_CA9X4_GPIO, NULL); 145 146static struct amba_device *ct_ca9x4_amba_devs[] __initdata = { 147 &clcd_device, 148 &dmc_device, 149 &smc_device, 150 &gpio_device, 151}; 152 153 154static long ct_round(struct clk *clk, unsigned long rate) 155{ 156 return rate; 157} 158 159static int ct_set(struct clk *clk, unsigned long rate) 160{ 161 return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_DB1 | 1, rate); 162} 163 164static const struct clk_ops osc1_clk_ops = { 165 .round = ct_round, 166 .set = ct_set, 167}; 168 169static struct clk osc1_clk = { 170 .ops = &osc1_clk_ops, 171 .rate = 24000000, 172}; 173 174static struct clk_lookup lookups[] = { 175 { /* CLCD */ 176 .dev_id = "ct:clcd", 177 .clk = &osc1_clk, 178 }, 179}; 180 181static struct resource pmu_resources[] = { 182 [0] = { 183 .start = IRQ_CT_CA9X4_PMU_CPU0, 184 .end = IRQ_CT_CA9X4_PMU_CPU0, 185 .flags = IORESOURCE_IRQ, 186 }, 187 [1] = { 188 .start = IRQ_CT_CA9X4_PMU_CPU1, 189 .end = IRQ_CT_CA9X4_PMU_CPU1, 190 .flags = IORESOURCE_IRQ, 191 }, 192 [2] = { 193 .start = IRQ_CT_CA9X4_PMU_CPU2, 194 .end = IRQ_CT_CA9X4_PMU_CPU2, 195 .flags = IORESOURCE_IRQ, 196 }, 197 [3] = { 198 .start = IRQ_CT_CA9X4_PMU_CPU3, 199 .end = IRQ_CT_CA9X4_PMU_CPU3, 200 .flags = IORESOURCE_IRQ, 201 }, 202}; 203 204static struct platform_device pmu_device = { 205 .name = "arm-pmu", 206 .id = ARM_PMU_DEVICE_CPU, 207 .num_resources = ARRAY_SIZE(pmu_resources), 208 .resource = pmu_resources, 209}; 210 211static void __init ct_ca9x4_init(void) 212{ 213 int i; 214 215#ifdef CONFIG_CACHE_L2X0 216 void __iomem *l2x0_base = MMIO_P2V(CT_CA9X4_L2CC); 217 218 /* set RAM latencies to 1 cycle for this core tile. */ 219 writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL); 220 writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL); 221 222 l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff); 223#endif 224 225 clkdev_add_table(lookups, ARRAY_SIZE(lookups)); 226 227 for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++) 228 amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource); 229 230 platform_device_register(&pmu_device); 231} 232 233MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4") 234 .phys_io = V2M_UART0 & SECTION_MASK, 235 .io_pg_offst = (__MMIO_P2V(V2M_UART0) >> 18) & 0xfffc, 236 .boot_params = PHYS_OFFSET + 0x00000100, 237 .map_io = ct_ca9x4_map_io, 238 .init_irq = ct_ca9x4_init_irq, 239 .timer = &v2m_timer, 240 .init_machine = ct_ca9x4_init, 241MACHINE_END 242