linux/arch/arm/mach-integrator/integrator_cp.c
<<
>>
Prefs
   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/device.h>
  15#include <linux/dma-mapping.h>
  16#include <linux/slab.h>
  17#include <linux/string.h>
  18#include <linux/sysdev.h>
  19
  20#include <asm/hardware.h>
  21#include <asm/io.h>
  22#include <asm/irq.h>
  23#include <asm/setup.h>
  24#include <asm/mach-types.h>
  25#include <asm/hardware/amba.h>
  26#include <asm/hardware/amba_kmi.h>
  27#include <asm/hardware/amba_clcd.h>
  28#include <asm/hardware/icst525.h>
  29
  30#include <asm/arch/cm.h>
  31#include <asm/arch/lm.h>
  32
  33#include <asm/mach/arch.h>
  34#include <asm/mach/flash.h>
  35#include <asm/mach/irq.h>
  36#include <asm/mach/mmc.h>
  37#include <asm/mach/map.h>
  38#include <asm/mach/time.h>
  39
  40#include "common.h"
  41#include "clock.h"
  42
  43#define INTCP_PA_MMC_BASE               0x1c000000
  44#define INTCP_PA_AACI_BASE              0x1d000000
  45
  46#define INTCP_PA_FLASH_BASE             0x24000000
  47#define INTCP_FLASH_SIZE                SZ_32M
  48
  49#define INTCP_PA_CLCD_BASE              0xc0000000
  50
  51#define INTCP_VA_CIC_BASE               0xf1000040
  52#define INTCP_VA_PIC_BASE               0xf1400000
  53#define INTCP_VA_SIC_BASE               0xfca00000
  54
  55#define INTCP_PA_ETH_BASE               0xc8000000
  56#define INTCP_ETH_SIZE                  0x10
  57
  58#define INTCP_VA_CTRL_BASE              0xfcb00000
  59#define INTCP_FLASHPROG                 0x04
  60#define CINTEGRATOR_FLASHPROG_FLVPPEN   (1 << 0)
  61#define CINTEGRATOR_FLASHPROG_FLWREN    (1 << 1)
  62
  63/*
  64 * Logical      Physical
  65 * f1000000     10000000        Core module registers
  66 * f1100000     11000000        System controller registers
  67 * f1200000     12000000        EBI registers
  68 * f1300000     13000000        Counter/Timer
  69 * f1400000     14000000        Interrupt controller
  70 * f1600000     16000000        UART 0
  71 * f1700000     17000000        UART 1
  72 * f1a00000     1a000000        Debug LEDs
  73 * f1b00000     1b000000        GPIO
  74 */
  75
  76static struct map_desc intcp_io_desc[] __initdata = {
  77 { IO_ADDRESS(INTEGRATOR_HDR_BASE),   INTEGRATOR_HDR_BASE,   SZ_4K,  MT_DEVICE },
  78 { IO_ADDRESS(INTEGRATOR_SC_BASE),    INTEGRATOR_SC_BASE,    SZ_4K,  MT_DEVICE },
  79 { IO_ADDRESS(INTEGRATOR_EBI_BASE),   INTEGRATOR_EBI_BASE,   SZ_4K,  MT_DEVICE },
  80 { IO_ADDRESS(INTEGRATOR_CT_BASE),    INTEGRATOR_CT_BASE,    SZ_4K,  MT_DEVICE },
  81 { IO_ADDRESS(INTEGRATOR_IC_BASE),    INTEGRATOR_IC_BASE,    SZ_4K,  MT_DEVICE },
  82 { IO_ADDRESS(INTEGRATOR_UART0_BASE), INTEGRATOR_UART0_BASE, SZ_4K,  MT_DEVICE },
  83 { IO_ADDRESS(INTEGRATOR_UART1_BASE), INTEGRATOR_UART1_BASE, SZ_4K,  MT_DEVICE },
  84 { IO_ADDRESS(INTEGRATOR_DBG_BASE),   INTEGRATOR_DBG_BASE,   SZ_4K,  MT_DEVICE },
  85 { IO_ADDRESS(INTEGRATOR_GPIO_BASE),  INTEGRATOR_GPIO_BASE,  SZ_4K,  MT_DEVICE },
  86 { 0xfc900000, 0xc9000000, SZ_4K, MT_DEVICE },
  87 { 0xfca00000, 0xca000000, SZ_4K, MT_DEVICE },
  88 { 0xfcb00000, 0xcb000000, SZ_4K, MT_DEVICE },
  89};
  90
  91static void __init intcp_map_io(void)
  92{
  93        iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));
  94}
  95
  96#define cic_writel      __raw_writel
  97#define cic_readl       __raw_readl
  98#define pic_writel      __raw_writel
  99#define pic_readl       __raw_readl
 100#define sic_writel      __raw_writel
 101#define sic_readl       __raw_readl
 102
 103static void cic_mask_irq(unsigned int irq)
 104{
 105        irq -= IRQ_CIC_START;
 106        cic_writel(1 << irq, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
 107}
 108
 109static void cic_unmask_irq(unsigned int irq)
 110{
 111        irq -= IRQ_CIC_START;
 112        cic_writel(1 << irq, INTCP_VA_CIC_BASE + IRQ_ENABLE_SET);
 113}
 114
 115static struct irqchip cic_chip = {
 116        .ack    = cic_mask_irq,
 117        .mask   = cic_mask_irq,
 118        .unmask = cic_unmask_irq,
 119};
 120
 121static void pic_mask_irq(unsigned int irq)
 122{
 123        irq -= IRQ_PIC_START;
 124        pic_writel(1 << irq, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
 125}
 126
 127static void pic_unmask_irq(unsigned int irq)
 128{
 129        irq -= IRQ_PIC_START;
 130        pic_writel(1 << irq, INTCP_VA_PIC_BASE + IRQ_ENABLE_SET);
 131}
 132
 133static struct irqchip pic_chip = {
 134        .ack    = pic_mask_irq,
 135        .mask   = pic_mask_irq,
 136        .unmask = pic_unmask_irq,
 137};
 138
 139static void sic_mask_irq(unsigned int irq)
 140{
 141        irq -= IRQ_SIC_START;
 142        sic_writel(1 << irq, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
 143}
 144
 145static void sic_unmask_irq(unsigned int irq)
 146{
 147        irq -= IRQ_SIC_START;
 148        sic_writel(1 << irq, INTCP_VA_SIC_BASE + IRQ_ENABLE_SET);
 149}
 150
 151static struct irqchip sic_chip = {
 152        .ack    = sic_mask_irq,
 153        .mask   = sic_mask_irq,
 154        .unmask = sic_unmask_irq,
 155};
 156
 157static void
 158sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
 159{
 160        unsigned long status = sic_readl(INTCP_VA_SIC_BASE + IRQ_STATUS);
 161
 162        if (status == 0) {
 163                do_bad_IRQ(irq, desc, regs);
 164                return;
 165        }
 166
 167        do {
 168                irq = ffs(status) - 1;
 169                status &= ~(1 << irq);
 170
 171                irq += IRQ_SIC_START;
 172
 173                desc = irq_desc + irq;
 174                desc->handle(irq, desc, regs);
 175        } while (status);
 176}
 177
 178static void __init intcp_init_irq(void)
 179{
 180        unsigned int i;
 181
 182        /*
 183         * Disable all interrupt sources
 184         */
 185        pic_writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
 186        pic_writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR);
 187
 188        for (i = IRQ_PIC_START; i <= IRQ_PIC_END; i++) {
 189                if (i == 11)
 190                        i = 22;
 191                if (i == IRQ_CP_CPPLDINT)
 192                        i++;
 193                if (i == 29)
 194                        break;
 195                set_irq_chip(i, &pic_chip);
 196                set_irq_handler(i, do_level_IRQ);
 197                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 198        }
 199
 200        cic_writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
 201        cic_writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR);
 202
 203        for (i = IRQ_CIC_START; i <= IRQ_CIC_END; i++) {
 204                set_irq_chip(i, &cic_chip);
 205                set_irq_handler(i, do_level_IRQ);
 206                set_irq_flags(i, IRQF_VALID);
 207        }
 208
 209        sic_writel(0x00000fff, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
 210        sic_writel(0x00000fff, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR);
 211
 212        for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) {
 213                set_irq_chip(i, &sic_chip);
 214                set_irq_handler(i, do_level_IRQ);
 215                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 216        }
 217
 218        set_irq_handler(IRQ_CP_CPPLDINT, sic_handle_irq);
 219        pic_unmask_irq(IRQ_CP_CPPLDINT);
 220}
 221
 222/*
 223 * Clock handling
 224 */
 225#define CM_LOCK (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
 226#define CM_AUXOSC (IO_ADDRESS(INTEGRATOR_HDR_BASE)+0x1c)
 227
 228static const struct icst525_params cp_auxvco_params = {
 229        .ref            = 24000,
 230        .vco_max        = 320000,
 231        .vd_min         = 8,
 232        .vd_max         = 263,
 233        .rd_min         = 3,
 234        .rd_max         = 65,
 235};
 236
 237static void cp_auxvco_set(struct clk *clk, struct icst525_vco vco)
 238{
 239        u32 val;
 240
 241        val = readl(CM_AUXOSC) & ~0x7ffff;
 242        val |= vco.v | (vco.r << 9) | (vco.s << 16);
 243
 244        writel(0xa05f, CM_LOCK);
 245        writel(val, CM_AUXOSC);
 246        writel(0, CM_LOCK);
 247}
 248
 249static struct clk cp_clcd_clk = {
 250        .name   = "CLCDCLK",
 251        .params = &cp_auxvco_params,
 252        .setvco = cp_auxvco_set,
 253};
 254
 255static struct clk cp_mmci_clk = {
 256        .name   = "MCLK",
 257        .rate   = 14745600,
 258};
 259
 260/*
 261 * Flash handling.
 262 */
 263static int intcp_flash_init(void)
 264{
 265        u32 val;
 266
 267        val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
 268        val |= CINTEGRATOR_FLASHPROG_FLWREN;
 269        writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
 270
 271        return 0;
 272}
 273
 274static void intcp_flash_exit(void)
 275{
 276        u32 val;
 277
 278        val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
 279        val &= ~(CINTEGRATOR_FLASHPROG_FLVPPEN|CINTEGRATOR_FLASHPROG_FLWREN);
 280        writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
 281}
 282
 283static void intcp_flash_set_vpp(int on)
 284{
 285        u32 val;
 286
 287        val = readl(INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
 288        if (on)
 289                val |= CINTEGRATOR_FLASHPROG_FLVPPEN;
 290        else
 291                val &= ~CINTEGRATOR_FLASHPROG_FLVPPEN;
 292        writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG);
 293}
 294
 295static struct flash_platform_data intcp_flash_data = {
 296        .map_name       = "cfi_probe",
 297        .width          = 4,
 298        .init           = intcp_flash_init,
 299        .exit           = intcp_flash_exit,
 300        .set_vpp        = intcp_flash_set_vpp,
 301};
 302
 303static struct resource intcp_flash_resource = {
 304        .start          = INTCP_PA_FLASH_BASE,
 305        .end            = INTCP_PA_FLASH_BASE + INTCP_FLASH_SIZE - 1,
 306        .flags          = IORESOURCE_MEM,
 307};
 308
 309static struct platform_device intcp_flash_device = {
 310        .name           = "armflash",
 311        .id             = 0,
 312        .dev            = {
 313                .platform_data  = &intcp_flash_data,
 314        },
 315        .num_resources  = 1,
 316        .resource       = &intcp_flash_resource,
 317};
 318
 319static struct resource smc91x_resources[] = {
 320        [0] = {
 321                .start  = INTCP_PA_ETH_BASE,
 322                .end    = INTCP_PA_ETH_BASE + INTCP_ETH_SIZE - 1,
 323                .flags  = IORESOURCE_MEM,
 324        },
 325        [1] = {
 326                .start  = IRQ_CP_ETHINT,
 327                .end    = IRQ_CP_ETHINT,
 328                .flags  = IORESOURCE_IRQ,
 329        },
 330};
 331
 332static struct platform_device smc91x_device = {
 333        .name           = "smc91x",
 334        .id             = 0,
 335        .num_resources  = ARRAY_SIZE(smc91x_resources),
 336        .resource       = smc91x_resources,
 337};
 338
 339static struct platform_device *intcp_devs[] __initdata = {
 340        &intcp_flash_device,
 341        &smc91x_device,
 342};
 343
 344/*
 345 * It seems that the card insertion interrupt remains active after
 346 * we've acknowledged it.  We therefore ignore the interrupt, and
 347 * rely on reading it from the SIC.  This also means that we must
 348 * clear the latched interrupt.
 349 */
 350static unsigned int mmc_status(struct device *dev)
 351{
 352        unsigned int status = readl(0xfca00004);
 353        writel(8, 0xfcb00008);
 354
 355        return status & 8;
 356}
 357
 358static struct mmc_platform_data mmc_data = {
 359        .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
 360        .status         = mmc_status,
 361};
 362
 363static struct amba_device mmc_device = {
 364        .dev            = {
 365                .bus_id = "mb:1c",
 366                .platform_data = &mmc_data,
 367        },
 368        .res            = {
 369                .start  = INTCP_PA_MMC_BASE,
 370                .end    = INTCP_PA_MMC_BASE + SZ_4K - 1,
 371                .flags  = IORESOURCE_MEM,
 372        },
 373        .irq            = { IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 },
 374        .periphid       = 0,
 375};
 376
 377static struct amba_device aaci_device = {
 378        .dev            = {
 379                .bus_id = "mb:1d",
 380        },
 381        .res            = {
 382                .start  = INTCP_PA_AACI_BASE,
 383                .end    = INTCP_PA_AACI_BASE + SZ_4K - 1,
 384                .flags  = IORESOURCE_MEM,
 385        },
 386        .irq            = { IRQ_CP_AACIINT, NO_IRQ },
 387        .periphid       = 0,
 388};
 389
 390
 391/*
 392 * CLCD support
 393 */
 394static struct clcd_panel vga = {
 395        .mode           = {
 396                .name           = "VGA",
 397                .refresh        = 60,
 398                .xres           = 640,
 399                .yres           = 480,
 400                .pixclock       = 39721,
 401                .left_margin    = 40,
 402                .right_margin   = 24,
 403                .upper_margin   = 32,
 404                .lower_margin   = 11,
 405                .hsync_len      = 96,
 406                .vsync_len      = 2,
 407                .sync           = 0,
 408                .vmode          = FB_VMODE_NONINTERLACED,
 409        },
 410        .width          = -1,
 411        .height         = -1,
 412        .tim2           = TIM2_BCD | TIM2_IPC,
 413        .cntl           = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
 414        .bpp            = 16,
 415        .grayscale      = 0,
 416};
 417
 418/*
 419 * Ensure VGA is selected.
 420 */
 421static void cp_clcd_enable(struct clcd_fb *fb)
 422{
 423        cm_control(CM_CTRL_LCDMUXSEL_MASK, CM_CTRL_LCDMUXSEL_VGA);
 424}
 425
 426static unsigned long framesize = SZ_1M;
 427
 428static int cp_clcd_setup(struct clcd_fb *fb)
 429{
 430        dma_addr_t dma;
 431
 432        fb->panel = &vga;
 433
 434        fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
 435                                                    &dma, GFP_KERNEL);
 436        if (!fb->fb.screen_base) {
 437                printk(KERN_ERR "CLCD: unable to map framebuffer\n");
 438                return -ENOMEM;
 439        }
 440
 441        fb->fb.fix.smem_start   = dma;
 442        fb->fb.fix.smem_len     = framesize;
 443
 444        return 0;
 445}
 446
 447static int cp_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
 448{
 449        return dma_mmap_writecombine(&fb->dev->dev, vma,
 450                                     fb->fb.screen_base,
 451                                     fb->fb.fix.smem_start,
 452                                     fb->fb.fix.smem_len);
 453}
 454
 455static void cp_clcd_remove(struct clcd_fb *fb)
 456{
 457        dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
 458                              fb->fb.screen_base, fb->fb.fix.smem_start);
 459}
 460
 461static struct clcd_board clcd_data = {
 462        .name           = "Integrator/CP",
 463        .check          = clcdfb_check,
 464        .decode         = clcdfb_decode,
 465        .enable         = cp_clcd_enable,
 466        .setup          = cp_clcd_setup,
 467        .mmap           = cp_clcd_mmap,
 468        .remove         = cp_clcd_remove,
 469};
 470
 471static struct amba_device clcd_device = {
 472        .dev            = {
 473                .bus_id = "mb:c0",
 474                .coherent_dma_mask = ~0,
 475                .platform_data = &clcd_data,
 476        },
 477        .res            = {
 478                .start  = INTCP_PA_CLCD_BASE,
 479                .end    = INTCP_PA_CLCD_BASE + SZ_4K - 1,
 480                .flags  = IORESOURCE_MEM,
 481        },
 482        .dma_mask       = ~0,
 483        .irq            = { IRQ_CP_CLCDCINT, NO_IRQ },
 484        .periphid       = 0,
 485};
 486
 487static struct amba_device *amba_devs[] __initdata = {
 488        &mmc_device,
 489        &aaci_device,
 490        &clcd_device,
 491};
 492
 493static void __init intcp_init(void)
 494{
 495        int i;
 496
 497        clk_register(&cp_clcd_clk);
 498        clk_register(&cp_mmci_clk);
 499
 500        platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));
 501
 502        for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
 503                struct amba_device *d = amba_devs[i];
 504                amba_device_register(d, &iomem_resource);
 505        }
 506}
 507
 508#define TIMER_CTRL_IE   (1 << 5)                        /* Interrupt Enable */
 509
 510static void __init intcp_timer_init(void)
 511{
 512        integrator_time_init(1000000 / HZ, TIMER_CTRL_IE);
 513}
 514
 515static struct sys_timer cp_timer = {
 516        .init           = intcp_timer_init,
 517        .offset         = integrator_gettimeoffset,
 518};
 519
 520MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
 521        MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd")
 522        BOOT_MEM(0x00000000, 0x16000000, 0xf1600000)
 523        BOOT_PARAMS(0x00000100)
 524        MAPIO(intcp_map_io)
 525        INITIRQ(intcp_init_irq)
 526        .timer          = &cp_timer,
 527        INIT_MACHINE(intcp_init)
 528MACHINE_END
 529
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.