1/* 2 * linux/arch/arm/mach-integrator/integrator_cp.c 3 * 4 * Copyright (C) 2003 Deep Blue Solutions Ltd 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License. 9 */ 10#include <linux/types.h> 11#include <linux/kernel.h> 12#include <linux/init.h> 13#include <linux/list.h> 14#include <linux/platform_device.h> 15#include <linux/dma-mapping.h> 16#include <linux/string.h> 17#include <linux/device.h> 18#include <linux/amba/bus.h> 19#include <linux/amba/kmi.h> 20#include <linux/amba/clcd.h> 21#include <linux/amba/mmci.h> 22#include <linux/io.h> 23#include <linux/gfp.h> 24#include <linux/clkdev.h> 25#include <linux/mtd/physmap.h> 26 27#include <mach/hardware.h> 28#include <mach/platform.h> 29#include <asm/setup.h> 30#include <asm/mach-types.h> 31#include <asm/hardware/arm_timer.h> 32#include <asm/hardware/icst.h> 33 34#include <mach/cm.h> 35#include <mach/lm.h> 36#include <mach/irqs.h> 37 38#include <asm/mach/arch.h> 39#include <asm/mach/irq.h> 40#include <asm/mach/map.h> 41#include <asm/mach/time.h> 42 43#include <asm/hardware/timer-sp.h> 44 45#include <plat/clcd.h> 46#include <plat/fpga-irq.h> 47#include <plat/sched_clock.h> 48 49#include "common.h" 50 51#define INTCP_PA_FLASH_BASE 0x24000000 52#define INTCP_FLASH_SIZE SZ_32M 53 54#define INTCP_PA_CLCD_BASE 0xc0000000 55 56#define INTCP_VA_CIC_BASE __io_address(INTEGRATOR_HDR_BASE + 0x40) 57#define INTCP_VA_PIC_BASE __io_address(INTEGRATOR_IC_BASE) 58#define INTCP_VA_SIC_BASE __io_address(INTEGRATOR_CP_SIC_BASE) 59 60#define INTCP_ETH_SIZE 0x10 61 62#define INTCP_VA_CTRL_BASE IO_ADDRESS(INTEGRATOR_CP_CTL_BASE) 63#define INTCP_FLASHPROG 0x04 64#define CINTEGRATOR_FLASHPROG_FLVPPEN (1 << 0) 65#define CINTEGRATOR_FLASHPROG_FLWREN (1 << 1) 66 67/* 68 * Logical Physical 69 * f1000000 10000000 Core module registers 70 * f1100000 11000000 System controller registers 71 * f1200000 12000000 EBI registers 72 * f1300000 13000000 Counter/Timer 73 * f1400000 14000000 Interrupt controller 74 * f1600000 16000000 UART 0 75 * f1700000 17000000 UART 1 76 * f1a00000 1a000000 Debug LEDs 77 * fc900000 c9000000 GPIO 78 * fca00000 ca000000 SIC 79 * fcb00000 cb000000 CP system control 80 */ 81 82static struct map_desc intcp_io_desc[] __initdata = { 83 { 84 .virtual = IO_ADDRESS(INTEGRATOR_HDR_BASE), 85 .pfn = __phys_to_pfn(INTEGRATOR_HDR_BASE), 86 .length = SZ_4K, 87 .type = MT_DEVICE 88 }, { 89 .virtual = IO_ADDRESS(INTEGRATOR_SC_BASE), 90 .pfn = __phys_to_pfn(INTEGRATOR_SC_BASE), 91 .length = SZ_4K, 92 .type = MT_DEVICE 93 }, { 94 .virtual = IO_ADDRESS(INTEGRATOR_EBI_BASE), 95 .pfn = __phys_to_pfn(INTEGRATOR_EBI_BASE), 96 .length = SZ_4K, 97 .type = MT_DEVICE 98 }, { 99 .virtual = IO_ADDRESS(INTEGRATOR_CT_BASE), 100 .pfn = __phys_to_pfn(INTEGRATOR_CT_BASE), 101 .length = SZ_4K, 102 .type = MT_DEVICE 103 }, { 104 .virtual = IO_ADDRESS(INTEGRATOR_IC_BASE), 105 .pfn = __phys_to_pfn(INTEGRATOR_IC_BASE), 106 .length = SZ_4K, 107 .type = MT_DEVICE 108 }, { 109 .virtual = IO_ADDRESS(INTEGRATOR_UART0_BASE), 110 .pfn = __phys_to_pfn(INTEGRATOR_UART0_BASE), 111 .length = SZ_4K, 112 .type = MT_DEVICE 113 }, { 114 .virtual = IO_ADDRESS(INTEGRATOR_UART1_BASE), 115 .pfn = __phys_to_pfn(INTEGRATOR_UART1_BASE), 116 .length = SZ_4K, 117 .type = MT_DEVICE 118 }, { 119 .virtual = IO_ADDRESS(INTEGRATOR_DBG_BASE), 120 .pfn = __phys_to_pfn(INTEGRATOR_DBG_BASE), 121 .length = SZ_4K, 122 .type = MT_DEVICE 123 }, { 124 .virtual = IO_ADDRESS(INTEGRATOR_CP_GPIO_BASE), 125 .pfn = __phys_to_pfn(INTEGRATOR_CP_GPIO_BASE), 126 .length = SZ_4K, 127 .type = MT_DEVICE 128 }, { 129 .virtual = IO_ADDRESS(INTEGRATOR_CP_SIC_BASE), 130 .pfn = __phys_to_pfn(INTEGRATOR_CP_SIC_BASE), 131 .length = SZ_4K, 132 .type = MT_DEVICE 133 }, { 134 .virtual = IO_ADDRESS(INTEGRATOR_CP_CTL_BASE), 135 .pfn = __phys_to_pfn(INTEGRATOR_CP_CTL_BASE), 136 .length = SZ_4K, 137 .type = MT_DEVICE 138 } 139}; 140 141static void __init intcp_map_io(void) 142{ 143 iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc)); 144} 145 146static struct fpga_irq_data cic_irq_data = { 147 .base = INTCP_VA_CIC_BASE, 148 .irq_start = IRQ_CIC_START, 149 .chip.name = "CIC", 150}; 151 152static struct fpga_irq_data pic_irq_data = { 153 .base = INTCP_VA_PIC_BASE, 154 .irq_start = IRQ_PIC_START, 155 .chip.name = "PIC", 156}; 157 158static struct fpga_irq_data sic_irq_data = { 159 .base = INTCP_VA_SIC_BASE, 160 .irq_start = IRQ_SIC_START, 161 .chip.name = "SIC", 162}; 163 164static void __init intcp_init_irq(void) 165{ 166 u32 pic_mask, sic_mask; 167 168 pic_mask = ~((~0u) << (11 - IRQ_PIC_START)); 169 pic_mask |= (~((~0u) << (29 - 22))) << 22; 170 sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START)); 171 172 /* 173 * Disable all interrupt sources 174 */ 175 writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR); 176 writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR); 177 writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR); 178 writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR); 179 writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR); 180 writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR); 181 182 fpga_irq_init(-1, pic_mask, &pic_irq_data); 183 184 fpga_irq_init(-1, ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START)), 185 &cic_irq_data); 186 187 fpga_irq_init(IRQ_CP_CPPLDINT, sic_mask, &sic_irq_data); 188} 189 190/* 191 * Clock handling 192 */ 193#define CM_LOCK (__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET) 194#define CM_AUXOSC (__io_address(INTEGRATOR_HDR_BASE)+0x1c) 195 196static const struct icst_params cp_auxvco_params = { 197 .ref = 24000000, 198 .vco_max = ICST525_VCO_MAX_5V, 199 .vco_min = ICST525_VCO_MIN, 200 .vd_min = 8, 201 .vd_max = 263, 202 .rd_min = 3, 203 .rd_max = 65, 204 .s2div = icst525_s2div, 205 .idx2s = icst525_idx2s, 206}; 207 208static void cp_auxvco_set(struct clk *clk, struct icst_vco vco) 209{ 210 u32 val; 211 212 val = readl(clk->vcoreg) & ~0x7ffff; 213 val |= vco.v | (vco.r << 9) | (vco.s << 16); 214 215 writel(0xa05f, CM_LOCK); 216 writel(val, clk->vcoreg); 217 writel(0, CM_LOCK); 218} 219 220static const struct clk_ops cp_auxclk_ops = { 221 .round = icst_clk_round, 222 .set = icst_clk_set, 223 .setvco = cp_auxvco_set, 224}; 225 226static struct clk cp_auxclk = { 227 .ops = &cp_auxclk_ops, 228 .params = &cp_auxvco_params, 229 .vcoreg = CM_AUXOSC, 230}; 231 232static struct clk sp804_clk = { 233 .rate = 1000000, 234}; 235 236static struct clk_lookup cp_lookups[] = { 237 { /* CLCD */ 238 .dev_id = "mb:c0", 239 .clk = &cp_auxclk, 240 }, { /* SP804 timers */ 241 .dev_id = "sp804", 242 .clk = &sp804_clk, 243 }, 244}; 245 246/* 247 * Flash handling. 248 */ 249static int intcp_flash_init(struct platform_device *dev) 250{ 251 u32 val; 252 253 val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG); 254 val |= CINTEGRATOR_FLASHPROG_FLWREN; 255 writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG); 256 257 return 0; 258} 259 260static void intcp_flash_exit(struct platform_device *dev) 261{ 262 u32 val; 263 264 val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG); 265 val &= ~(CINTEGRATOR_FLASHPROG_FLVPPEN|CINTEGRATOR_FLASHPROG_FLWREN); 266 writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG); 267} 268 269static void intcp_flash_set_vpp(struct platform_device *pdev, int on) 270{ 271 u32 val; 272 273 val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG); 274 if (on) 275 val |= CINTEGRATOR_FLASHPROG_FLVPPEN; 276 else 277 val &= ~CINTEGRATOR_FLASHPROG_FLVPPEN; 278 writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG); 279} 280 281static struct physmap_flash_data intcp_flash_data = { 282 .width = 4, 283 .init = intcp_flash_init, 284 .exit = intcp_flash_exit, 285 .set_vpp = intcp_flash_set_vpp, 286}; 287 288static struct resource intcp_flash_resource = { 289 .start = INTCP_PA_FLASH_BASE, 290 .end = INTCP_PA_FLASH_BASE + INTCP_FLASH_SIZE - 1, 291 .flags = IORESOURCE_MEM, 292}; 293 294static struct platform_device intcp_flash_device = { 295 .name = "physmap-flash", 296 .id = 0, 297 .dev = { 298 .platform_data = &intcp_flash_data, 299 }, 300 .num_resources = 1, 301 .resource = &intcp_flash_resource, 302}; 303 304static struct resource smc91x_resources[] = { 305 [0] = { 306 .start = INTEGRATOR_CP_ETH_BASE, 307 .end = INTEGRATOR_CP_ETH_BASE + INTCP_ETH_SIZE - 1, 308 .flags = IORESOURCE_MEM, 309 }, 310 [1] = { 311 .start = IRQ_CP_ETHINT, 312 .end = IRQ_CP_ETHINT, 313 .flags = IORESOURCE_IRQ, 314 }, 315}; 316 317static struct platform_device smc91x_device = { 318 .name = "smc91x", 319 .id = 0, 320 .num_resources = ARRAY_SIZE(smc91x_resources), 321 .resource = smc91x_resources, 322}; 323 324static struct platform_device *intcp_devs[] __initdata = { 325 &intcp_flash_device, 326 &smc91x_device, 327}; 328 329/* 330 * It seems that the card insertion interrupt remains active after 331 * we've acknowledged it. We therefore ignore the interrupt, and 332 * rely on reading it from the SIC. This also means that we must 333 * clear the latched interrupt. 334 */ 335static unsigned int mmc_status(struct device *dev) 336{ 337 unsigned int status = readl(IO_ADDRESS(0xca000000 + 4)); 338 writel(8, IO_ADDRESS(INTEGRATOR_CP_CTL_BASE + 8)); 339 340 return status & 8; 341} 342 343static struct mmci_platform_data mmc_data = { 344 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, 345 .status = mmc_status, 346 .gpio_wp = -1, 347 .gpio_cd = -1, 348}; 349 350#define INTEGRATOR_CP_MMC_IRQS { IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 } 351#define INTEGRATOR_CP_AACI_IRQS { IRQ_CP_AACIINT } 352 353static AMBA_APB_DEVICE(mmc, "mb:1c", 0, INTEGRATOR_CP_MMC_BASE, 354 INTEGRATOR_CP_MMC_IRQS, &mmc_data); 355 356static AMBA_APB_DEVICE(aaci, "mb:1d", 0, INTEGRATOR_CP_AACI_BASE, 357 INTEGRATOR_CP_AACI_IRQS, NULL); 358 359 360/* 361 * CLCD support 362 */ 363/* 364 * Ensure VGA is selected. 365 */ 366static void cp_clcd_enable(struct clcd_fb *fb) 367{ 368 struct fb_var_screeninfo *var = &fb->fb.var; 369 u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2; 370 371 if (var->bits_per_pixel <= 8 || 372 (var->bits_per_pixel == 16 && var->green.length == 5)) 373 /* Pseudocolor, RGB555, BGR555 */ 374 val |= CM_CTRL_LCDMUXSEL_VGA555_TFT555; 375 else if (fb->fb.var.bits_per_pixel <= 16) 376 /* truecolor RGB565 */ 377 val |= CM_CTRL_LCDMUXSEL_VGA565_TFT555; 378 else 379 val = 0; /* no idea for this, don't trust the docs */ 380 381 cm_control(CM_CTRL_LCDMUXSEL_MASK| 382 CM_CTRL_LCDEN0| 383 CM_CTRL_LCDEN1| 384 CM_CTRL_STATIC1| 385 CM_CTRL_STATIC2| 386 CM_CTRL_STATIC| 387 CM_CTRL_n24BITEN, val); 388} 389 390static int cp_clcd_setup(struct clcd_fb *fb) 391{ 392 fb->panel = versatile_clcd_get_panel("VGA"); 393 if (!fb->panel) 394 return -EINVAL; 395 396 return versatile_clcd_setup_dma(fb, SZ_1M); 397} 398 399static struct clcd_board clcd_data = { 400 .name = "Integrator/CP", 401 .caps = CLCD_CAP_5551 | CLCD_CAP_RGB565 | CLCD_CAP_888, 402 .check = clcdfb_check, 403 .decode = clcdfb_decode, 404 .enable = cp_clcd_enable, 405 .setup = cp_clcd_setup, 406 .mmap = versatile_clcd_mmap_dma, 407 .remove = versatile_clcd_remove_dma, 408}; 409 410static AMBA_AHB_DEVICE(clcd, "mb:c0", 0, INTCP_PA_CLCD_BASE, 411 { IRQ_CP_CLCDCINT }, &clcd_data); 412 413static struct amba_device *amba_devs[] __initdata = { 414 &mmc_device, 415 &aaci_device, 416 &clcd_device, 417}; 418 419#define REFCOUNTER (__io_address(INTEGRATOR_HDR_BASE) + 0x28) 420 421static void __init intcp_init_early(void) 422{ 423 clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups)); 424 425 integrator_init_early(); 426 427#ifdef CONFIG_PLAT_VERSATILE_SCHED_CLOCK 428 versatile_sched_clock_init(REFCOUNTER, 24000000); 429#endif 430} 431 432static void __init intcp_init(void) 433{ 434 int i; 435 436 platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs)); 437 438 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { 439 struct amba_device *d = amba_devs[i]; 440 amba_device_register(d, &iomem_resource); 441 } 442} 443 444#define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE) 445#define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE) 446#define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE) 447 448static void __init intcp_timer_init(void) 449{ 450 writel(0, TIMER0_VA_BASE + TIMER_CTRL); 451 writel(0, TIMER1_VA_BASE + TIMER_CTRL); 452 writel(0, TIMER2_VA_BASE + TIMER_CTRL); 453 454 sp804_clocksource_init(TIMER2_VA_BASE, "timer2"); 455 sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1, "timer1"); 456} 457 458static struct sys_timer cp_timer = { 459 .init = intcp_timer_init, 460}; 461 462MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP") 463 /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ 464 .atag_offset = 0x100, 465 .reserve = integrator_reserve, 466 .map_io = intcp_map_io, 467 .nr_irqs = NR_IRQS_INTEGRATOR_CP, 468 .init_early = intcp_init_early, 469 .init_irq = intcp_init_irq, 470 .timer = &cp_timer, 471 .init_machine = intcp_init, 472 .restart = integrator_restart, 473MACHINE_END 474