linux/arch/arm/mach-realview/core.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/mach-realview/core.c
   3 *
   4 *  Copyright (C) 1999 - 2003 ARM Limited
   5 *  Copyright (C) 2000 Deep Blue Solutions Ltd
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20 */
  21#include <linux/init.h>
  22#include <linux/platform_device.h>
  23#include <linux/dma-mapping.h>
  24#include <linux/sysdev.h>
  25#include <linux/interrupt.h>
  26#include <linux/amba/bus.h>
  27#include <linux/amba/clcd.h>
  28#include <linux/clocksource.h>
  29#include <linux/clockchips.h>
  30#include <linux/io.h>
  31#include <linux/smsc911x.h>
  32#include <linux/ata_platform.h>
  33#include <linux/amba/mmci.h>
  34
  35#include <asm/clkdev.h>
  36#include <asm/system.h>
  37#include <mach/hardware.h>
  38#include <asm/irq.h>
  39#include <asm/leds.h>
  40#include <asm/mach-types.h>
  41#include <asm/hardware/arm_timer.h>
  42#include <asm/hardware/icst307.h>
  43
  44#include <asm/mach/arch.h>
  45#include <asm/mach/flash.h>
  46#include <asm/mach/irq.h>
  47#include <asm/mach/map.h>
  48
  49#include <asm/hardware/gic.h>
  50
  51#include <mach/platform.h>
  52#include <mach/irqs.h>
  53
  54#include "core.h"
  55#include "clock.h"
  56
  57#define REALVIEW_REFCOUNTER     (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET)
  58
  59/* used by entry-macro.S and platsmp.c */
  60void __iomem *gic_cpu_base_addr;
  61
  62#ifdef CONFIG_ZONE_DMA
  63/*
  64 * Adjust the zones if there are restrictions for DMA access.
  65 */
  66void __init realview_adjust_zones(int node, unsigned long *size,
  67                                  unsigned long *hole)
  68{
  69        unsigned long dma_size = SZ_256M >> PAGE_SHIFT;
  70
  71        if (!machine_is_realview_pbx() || node || (size[0] <= dma_size))
  72                return;
  73
  74        size[ZONE_NORMAL] = size[0] - dma_size;
  75        size[ZONE_DMA] = dma_size;
  76        hole[ZONE_NORMAL] = hole[0];
  77        hole[ZONE_DMA] = 0;
  78}
  79#endif
  80
  81/*
  82 * This is the RealView sched_clock implementation.  This has
  83 * a resolution of 41.7ns, and a maximum value of about 179s.
  84 */
  85unsigned long long sched_clock(void)
  86{
  87        unsigned long long v;
  88
  89        v = (unsigned long long)readl(REALVIEW_REFCOUNTER) * 125;
  90        do_div(v, 3);
  91
  92        return v;
  93}
  94
  95
  96#define REALVIEW_FLASHCTRL    (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_FLASH_OFFSET)
  97
  98static int realview_flash_init(void)
  99{
 100        u32 val;
 101
 102        val = __raw_readl(REALVIEW_FLASHCTRL);
 103        val &= ~REALVIEW_FLASHPROG_FLVPPEN;
 104        __raw_writel(val, REALVIEW_FLASHCTRL);
 105
 106        return 0;
 107}
 108
 109static void realview_flash_exit(void)
 110{
 111        u32 val;
 112
 113        val = __raw_readl(REALVIEW_FLASHCTRL);
 114        val &= ~REALVIEW_FLASHPROG_FLVPPEN;
 115        __raw_writel(val, REALVIEW_FLASHCTRL);
 116}
 117
 118static void realview_flash_set_vpp(int on)
 119{
 120        u32 val;
 121
 122        val = __raw_readl(REALVIEW_FLASHCTRL);
 123        if (on)
 124                val |= REALVIEW_FLASHPROG_FLVPPEN;
 125        else
 126                val &= ~REALVIEW_FLASHPROG_FLVPPEN;
 127        __raw_writel(val, REALVIEW_FLASHCTRL);
 128}
 129
 130static struct flash_platform_data realview_flash_data = {
 131        .map_name               = "cfi_probe",
 132        .width                  = 4,
 133        .init                   = realview_flash_init,
 134        .exit                   = realview_flash_exit,
 135        .set_vpp                = realview_flash_set_vpp,
 136};
 137
 138struct platform_device realview_flash_device = {
 139        .name                   = "armflash",
 140        .id                     = 0,
 141        .dev                    = {
 142                .platform_data  = &realview_flash_data,
 143        },
 144};
 145
 146int realview_flash_register(struct resource *res, u32 num)
 147{
 148        realview_flash_device.resource = res;
 149        realview_flash_device.num_resources = num;
 150        return platform_device_register(&realview_flash_device);
 151}
 152
 153static struct smsc911x_platform_config smsc911x_config = {
 154        .flags          = SMSC911X_USE_32BIT,
 155        .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
 156        .irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
 157        .phy_interface  = PHY_INTERFACE_MODE_MII,
 158};
 159
 160static struct platform_device realview_eth_device = {
 161        .name           = "smsc911x",
 162        .id             = 0,
 163        .num_resources  = 2,
 164};
 165
 166int realview_eth_register(const char *name, struct resource *res)
 167{
 168        if (name)
 169                realview_eth_device.name = name;
 170        realview_eth_device.resource = res;
 171        if (strcmp(realview_eth_device.name, "smsc911x") == 0)
 172                realview_eth_device.dev.platform_data = &smsc911x_config;
 173
 174        return platform_device_register(&realview_eth_device);
 175}
 176
 177struct platform_device realview_usb_device = {
 178        .name                   = "isp1760",
 179        .num_resources          = 2,
 180};
 181
 182int realview_usb_register(struct resource *res)
 183{
 184        realview_usb_device.resource = res;
 185        return platform_device_register(&realview_usb_device);
 186}
 187
 188static struct pata_platform_info pata_platform_data = {
 189        .ioport_shift           = 1,
 190};
 191
 192static struct resource pata_resources[] = {
 193        [0] = {
 194                .start          = REALVIEW_CF_BASE,
 195                .end            = REALVIEW_CF_BASE + 0xff,
 196                .flags          = IORESOURCE_MEM,
 197        },
 198        [1] = {
 199                .start          = REALVIEW_CF_BASE + 0x100,
 200                .end            = REALVIEW_CF_BASE + SZ_4K - 1,
 201                .flags          = IORESOURCE_MEM,
 202        },
 203};
 204
 205struct platform_device realview_cf_device = {
 206        .name                   = "pata_platform",
 207        .id                     = -1,
 208        .num_resources          = ARRAY_SIZE(pata_resources),
 209        .resource               = pata_resources,
 210        .dev                    = {
 211                .platform_data  = &pata_platform_data,
 212        },
 213};
 214
 215static struct resource realview_i2c_resource = {
 216        .start          = REALVIEW_I2C_BASE,
 217        .end            = REALVIEW_I2C_BASE + SZ_4K - 1,
 218        .flags          = IORESOURCE_MEM,
 219};
 220
 221struct platform_device realview_i2c_device = {
 222        .name           = "versatile-i2c",
 223        .id             = 0,
 224        .num_resources  = 1,
 225        .resource       = &realview_i2c_resource,
 226};
 227
 228static struct i2c_board_info realview_i2c_board_info[] = {
 229        {
 230                I2C_BOARD_INFO("ds1338", 0xd0 >> 1),
 231        },
 232};
 233
 234static int __init realview_i2c_init(void)
 235{
 236        return i2c_register_board_info(0, realview_i2c_board_info,
 237                                       ARRAY_SIZE(realview_i2c_board_info));
 238}
 239arch_initcall(realview_i2c_init);
 240
 241#define REALVIEW_SYSMCI (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_MCI_OFFSET)
 242
 243/*
 244 * This is only used if GPIOLIB support is disabled
 245 */
 246static unsigned int realview_mmc_status(struct device *dev)
 247{
 248        struct amba_device *adev = container_of(dev, struct amba_device, dev);
 249        u32 mask;
 250
 251        if (adev->res.start == REALVIEW_MMCI0_BASE)
 252                mask = 1;
 253        else
 254                mask = 2;
 255
 256        return readl(REALVIEW_SYSMCI) & mask;
 257}
 258
 259struct mmci_platform_data realview_mmc0_plat_data = {
 260        .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
 261        .status         = realview_mmc_status,
 262        .gpio_wp        = 17,
 263        .gpio_cd        = 16,
 264};
 265
 266struct mmci_platform_data realview_mmc1_plat_data = {
 267        .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
 268        .status         = realview_mmc_status,
 269        .gpio_wp        = 19,
 270        .gpio_cd        = 18,
 271};
 272
 273/*
 274 * Clock handling
 275 */
 276static const struct icst307_params realview_oscvco_params = {
 277        .ref            = 24000,
 278        .vco_max        = 200000,
 279        .vd_min         = 4 + 8,
 280        .vd_max         = 511 + 8,
 281        .rd_min         = 1 + 2,
 282        .rd_max         = 127 + 2,
 283};
 284
 285static void realview_oscvco_set(struct clk *clk, struct icst307_vco vco)
 286{
 287        void __iomem *sys_lock = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LOCK_OFFSET;
 288        void __iomem *sys_osc;
 289        u32 val;
 290
 291        if (machine_is_realview_pb1176())
 292                sys_osc = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC0_OFFSET;
 293        else
 294                sys_osc = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC4_OFFSET;
 295
 296        val = readl(sys_osc) & ~0x7ffff;
 297        val |= vco.v | (vco.r << 9) | (vco.s << 16);
 298
 299        writel(0xa05f, sys_lock);
 300        writel(val, sys_osc);
 301        writel(0, sys_lock);
 302}
 303
 304static struct clk oscvco_clk = {
 305        .params = &realview_oscvco_params,
 306        .setvco = realview_oscvco_set,
 307};
 308
 309/*
 310 * These are fixed clocks.
 311 */
 312static struct clk ref24_clk = {
 313        .rate   = 24000000,
 314};
 315
 316static struct clk_lookup lookups[] = {
 317        {       /* UART0 */
 318                .dev_id         = "dev:uart0",
 319                .clk            = &ref24_clk,
 320        }, {    /* UART1 */
 321                .dev_id         = "dev:uart1",
 322                .clk            = &ref24_clk,
 323        }, {    /* UART2 */
 324                .dev_id         = "dev:uart2",
 325                .clk            = &ref24_clk,
 326        }, {    /* UART3 */
 327                .dev_id         = "fpga:uart3",
 328                .clk            = &ref24_clk,
 329        }, {    /* KMI0 */
 330                .dev_id         = "fpga:kmi0",
 331                .clk            = &ref24_clk,
 332        }, {    /* KMI1 */
 333                .dev_id         = "fpga:kmi1",
 334                .clk            = &ref24_clk,
 335        }, {    /* MMC0 */
 336                .dev_id         = "fpga:mmc0",
 337                .clk            = &ref24_clk,
 338        }, {    /* EB:CLCD */
 339                .dev_id         = "dev:clcd",
 340                .clk            = &oscvco_clk,
 341        }, {    /* PB:CLCD */
 342                .dev_id         = "issp:clcd",
 343                .clk            = &oscvco_clk,
 344        }
 345};
 346
 347static int __init clk_init(void)
 348{
 349        int i;
 350
 351        for (i = 0; i < ARRAY_SIZE(lookups); i++)
 352                clkdev_add(&lookups[i]);
 353        return 0;
 354}
 355arch_initcall(clk_init);
 356
 357/*
 358 * CLCD support.
 359 */
 360#define SYS_CLCD_NLCDIOON       (1 << 2)
 361#define SYS_CLCD_VDDPOSSWITCH   (1 << 3)
 362#define SYS_CLCD_PWR3V5SWITCH   (1 << 4)
 363#define SYS_CLCD_ID_MASK        (0x1f << 8)
 364#define SYS_CLCD_ID_SANYO_3_8   (0x00 << 8)
 365#define SYS_CLCD_ID_UNKNOWN_8_4 (0x01 << 8)
 366#define SYS_CLCD_ID_EPSON_2_2   (0x02 << 8)
 367#define SYS_CLCD_ID_SANYO_2_5   (0x07 << 8)
 368#define SYS_CLCD_ID_VGA         (0x1f << 8)
 369
 370static struct clcd_panel vga = {
 371        .mode           = {
 372                .name           = "VGA",
 373                .refresh        = 60,
 374                .xres           = 640,
 375                .yres           = 480,
 376                .pixclock       = 39721,
 377                .left_margin    = 40,
 378                .right_margin   = 24,
 379                .upper_margin   = 32,
 380                .lower_margin   = 11,
 381                .hsync_len      = 96,
 382                .vsync_len      = 2,
 383                .sync           = 0,
 384                .vmode          = FB_VMODE_NONINTERLACED,
 385        },
 386        .width          = -1,
 387        .height         = -1,
 388        .tim2           = TIM2_BCD | TIM2_IPC,
 389        .cntl           = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
 390        .bpp            = 16,
 391};
 392
 393static struct clcd_panel xvga = {
 394        .mode           = {
 395                .name           = "XVGA",
 396                .refresh        = 60,
 397                .xres           = 1024,
 398                .yres           = 768,
 399                .pixclock       = 15748,
 400                .left_margin    = 152,
 401                .right_margin   = 48,
 402                .upper_margin   = 23,
 403                .lower_margin   = 3,
 404                .hsync_len      = 104,
 405                .vsync_len      = 4,
 406                .sync           = 0,
 407                .vmode          = FB_VMODE_NONINTERLACED,
 408        },
 409        .width          = -1,
 410        .height         = -1,
 411        .tim2           = TIM2_BCD | TIM2_IPC,
 412        .cntl           = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
 413        .bpp            = 16,
 414};
 415
 416static struct clcd_panel sanyo_3_8_in = {
 417        .mode           = {
 418                .name           = "Sanyo QVGA",
 419                .refresh        = 116,
 420                .xres           = 320,
 421                .yres           = 240,
 422                .pixclock       = 100000,
 423                .left_margin    = 6,
 424                .right_margin   = 6,
 425                .upper_margin   = 5,
 426                .lower_margin   = 5,
 427                .hsync_len      = 6,
 428                .vsync_len      = 6,
 429                .sync           = 0,
 430                .vmode          = FB_VMODE_NONINTERLACED,
 431        },
 432        .width          = -1,
 433        .height         = -1,
 434        .tim2           = TIM2_BCD,
 435        .cntl           = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
 436        .bpp            = 16,
 437};
 438
 439static struct clcd_panel sanyo_2_5_in = {
 440        .mode           = {
 441                .name           = "Sanyo QVGA Portrait",
 442                .refresh        = 116,
 443                .xres           = 240,
 444                .yres           = 320,
 445                .pixclock       = 100000,
 446                .left_margin    = 20,
 447                .right_margin   = 10,
 448                .upper_margin   = 2,
 449                .lower_margin   = 2,
 450                .hsync_len      = 10,
 451                .vsync_len      = 2,
 452                .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
 453                .vmode          = FB_VMODE_NONINTERLACED,
 454        },
 455        .width          = -1,
 456        .height         = -1,
 457        .tim2           = TIM2_IVS | TIM2_IHS | TIM2_IPC,
 458        .cntl           = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
 459        .bpp            = 16,
 460};
 461
 462static struct clcd_panel epson_2_2_in = {
 463        .mode           = {
 464                .name           = "Epson QCIF",
 465                .refresh        = 390,
 466                .xres           = 176,
 467                .yres           = 220,
 468                .pixclock       = 62500,
 469                .left_margin    = 3,
 470                .right_margin   = 2,
 471                .upper_margin   = 1,
 472                .lower_margin   = 0,
 473                .hsync_len      = 3,
 474                .vsync_len      = 2,
 475                .sync           = 0,
 476                .vmode          = FB_VMODE_NONINTERLACED,
 477        },
 478        .width          = -1,
 479        .height         = -1,
 480        .tim2           = TIM2_BCD | TIM2_IPC,
 481        .cntl           = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
 482        .bpp            = 16,
 483};
 484
 485/*
 486 * Detect which LCD panel is connected, and return the appropriate
 487 * clcd_panel structure.  Note: we do not have any information on
 488 * the required timings for the 8.4in panel, so we presently assume
 489 * VGA timings.
 490 */
 491static struct clcd_panel *realview_clcd_panel(void)
 492{
 493        void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
 494        struct clcd_panel *vga_panel;
 495        struct clcd_panel *panel;
 496        u32 val;
 497
 498        if (machine_is_realview_eb())
 499                vga_panel = &vga;
 500        else
 501                vga_panel = &xvga;
 502
 503        val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
 504        if (val == SYS_CLCD_ID_SANYO_3_8)
 505                panel = &sanyo_3_8_in;
 506        else if (val == SYS_CLCD_ID_SANYO_2_5)
 507                panel = &sanyo_2_5_in;
 508        else if (val == SYS_CLCD_ID_EPSON_2_2)
 509                panel = &epson_2_2_in;
 510        else if (val == SYS_CLCD_ID_VGA)
 511                panel = vga_panel;
 512        else {
 513                printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
 514                        val);
 515                panel = vga_panel;
 516        }
 517
 518        return panel;
 519}
 520
 521/*
 522 * Disable all display connectors on the interface module.
 523 */
 524static void realview_clcd_disable(struct clcd_fb *fb)
 525{
 526        void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
 527        u32 val;
 528
 529        val = readl(sys_clcd);
 530        val &= ~SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
 531        writel(val, sys_clcd);
 532}
 533
 534/*
 535 * Enable the relevant connector on the interface module.
 536 */
 537static void realview_clcd_enable(struct clcd_fb *fb)
 538{
 539        void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
 540        u32 val;
 541
 542        /*
 543         * Enable the PSUs
 544         */
 545        val = readl(sys_clcd);
 546        val |= SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
 547        writel(val, sys_clcd);
 548}
 549
 550static int realview_clcd_setup(struct clcd_fb *fb)
 551{
 552        unsigned long framesize;
 553        dma_addr_t dma;
 554
 555        if (machine_is_realview_eb())
 556                /* VGA, 16bpp */
 557                framesize = 640 * 480 * 2;
 558        else
 559                /* XVGA, 16bpp */
 560                framesize = 1024 * 768 * 2;
 561
 562        fb->panel               = realview_clcd_panel();
 563
 564        fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
 565                                                    &dma, GFP_KERNEL | GFP_DMA);
 566        if (!fb->fb.screen_base) {
 567                printk(KERN_ERR "CLCD: unable to map framebuffer\n");
 568                return -ENOMEM;
 569        }
 570
 571        fb->fb.fix.smem_start   = dma;
 572        fb->fb.fix.smem_len     = framesize;
 573
 574        return 0;
 575}
 576
 577static int realview_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
 578{
 579        return dma_mmap_writecombine(&fb->dev->dev, vma,
 580                                     fb->fb.screen_base,
 581                                     fb->fb.fix.smem_start,
 582                                     fb->fb.fix.smem_len);
 583}
 584
 585static void realview_clcd_remove(struct clcd_fb *fb)
 586{
 587        dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
 588                              fb->fb.screen_base, fb->fb.fix.smem_start);
 589}
 590
 591struct clcd_board clcd_plat_data = {
 592        .name           = "RealView",
 593        .check          = clcdfb_check,
 594        .decode         = clcdfb_decode,
 595        .disable        = realview_clcd_disable,
 596        .enable         = realview_clcd_enable,
 597        .setup          = realview_clcd_setup,
 598        .mmap           = realview_clcd_mmap,
 599        .remove         = realview_clcd_remove,
 600};
 601
 602#ifdef CONFIG_LEDS
 603#define VA_LEDS_BASE (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LED_OFFSET)
 604
 605void realview_leds_event(led_event_t ledevt)
 606{
 607        unsigned long flags;
 608        u32 val;
 609        u32 led = 1 << smp_processor_id();
 610
 611        local_irq_save(flags);
 612        val = readl(VA_LEDS_BASE);
 613
 614        switch (ledevt) {
 615        case led_idle_start:
 616                val = val & ~led;
 617                break;
 618
 619        case led_idle_end:
 620                val = val | led;
 621                break;
 622
 623        case led_timer:
 624                val = val ^ REALVIEW_SYS_LED7;
 625                break;
 626
 627        case led_halted:
 628                val = 0;
 629                break;
 630
 631        default:
 632                break;
 633        }
 634
 635        writel(val, VA_LEDS_BASE);
 636        local_irq_restore(flags);
 637}
 638#endif  /* CONFIG_LEDS */
 639
 640/*
 641 * Where is the timer (VA)?
 642 */
 643void __iomem *timer0_va_base;
 644void __iomem *timer1_va_base;
 645void __iomem *timer2_va_base;
 646void __iomem *timer3_va_base;
 647
 648/*
 649 * How long is the timer interval?
 650 */
 651#define TIMER_INTERVAL  (TICKS_PER_uSEC * mSEC_10)
 652#if TIMER_INTERVAL >= 0x100000
 653#define TIMER_RELOAD    (TIMER_INTERVAL >> 8)
 654#define TIMER_DIVISOR   (TIMER_CTRL_DIV256)
 655#define TICKS2USECS(x)  (256 * (x) / TICKS_PER_uSEC)
 656#elif TIMER_INTERVAL >= 0x10000
 657#define TIMER_RELOAD    (TIMER_INTERVAL >> 4)           /* Divide by 16 */
 658#define TIMER_DIVISOR   (TIMER_CTRL_DIV16)
 659#define TICKS2USECS(x)  (16 * (x) / TICKS_PER_uSEC)
 660#else
 661#define TIMER_RELOAD    (TIMER_INTERVAL)
 662#define TIMER_DIVISOR   (TIMER_CTRL_DIV1)
 663#define TICKS2USECS(x)  ((x) / TICKS_PER_uSEC)
 664#endif
 665
 666static void timer_set_mode(enum clock_event_mode mode,
 667                           struct clock_event_device *clk)
 668{
 669        unsigned long ctrl;
 670
 671        switch(mode) {
 672        case CLOCK_EVT_MODE_PERIODIC:
 673                writel(TIMER_RELOAD, timer0_va_base + TIMER_LOAD);
 674
 675                ctrl = TIMER_CTRL_PERIODIC;
 676                ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE;
 677                break;
 678        case CLOCK_EVT_MODE_ONESHOT:
 679                /* period set, and timer enabled in 'next_event' hook */
 680                ctrl = TIMER_CTRL_ONESHOT;
 681                ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE;
 682                break;
 683        case CLOCK_EVT_MODE_UNUSED:
 684        case CLOCK_EVT_MODE_SHUTDOWN:
 685        default:
 686                ctrl = 0;
 687        }
 688
 689        writel(ctrl, timer0_va_base + TIMER_CTRL);
 690}
 691
 692static int timer_set_next_event(unsigned long evt,
 693                                struct clock_event_device *unused)
 694{
 695        unsigned long ctrl = readl(timer0_va_base + TIMER_CTRL);
 696
 697        writel(evt, timer0_va_base + TIMER_LOAD);
 698        writel(ctrl | TIMER_CTRL_ENABLE, timer0_va_base + TIMER_CTRL);
 699
 700        return 0;
 701}
 702
 703static struct clock_event_device timer0_clockevent =     {
 704        .name           = "timer0",
 705        .shift          = 32,
 706        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
 707        .set_mode       = timer_set_mode,
 708        .set_next_event = timer_set_next_event,
 709        .rating         = 300,
 710        .cpumask        = cpu_all_mask,
 711};
 712
 713static void __init realview_clockevents_init(unsigned int timer_irq)
 714{
 715        timer0_clockevent.irq = timer_irq;
 716        timer0_clockevent.mult =
 717                div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift);
 718        timer0_clockevent.max_delta_ns =
 719                clockevent_delta2ns(0xffffffff, &timer0_clockevent);
 720        timer0_clockevent.min_delta_ns =
 721                clockevent_delta2ns(0xf, &timer0_clockevent);
 722
 723        clockevents_register_device(&timer0_clockevent);
 724}
 725
 726/*
 727 * IRQ handler for the timer
 728 */
 729static irqreturn_t realview_timer_interrupt(int irq, void *dev_id)
 730{
 731        struct clock_event_device *evt = &timer0_clockevent;
 732
 733        /* clear the interrupt */
 734        writel(1, timer0_va_base + TIMER_INTCLR);
 735
 736        evt->event_handler(evt);
 737
 738        return IRQ_HANDLED;
 739}
 740
 741static struct irqaction realview_timer_irq = {
 742        .name           = "RealView Timer Tick",
 743        .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
 744        .handler        = realview_timer_interrupt,
 745};
 746
 747static cycle_t realview_get_cycles(struct clocksource *cs)
 748{
 749        return ~readl(timer3_va_base + TIMER_VALUE);
 750}
 751
 752static struct clocksource clocksource_realview = {
 753        .name   = "timer3",
 754        .rating = 200,
 755        .read   = realview_get_cycles,
 756        .mask   = CLOCKSOURCE_MASK(32),
 757        .shift  = 20,
 758        .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 759};
 760
 761static void __init realview_clocksource_init(void)
 762{
 763        /* setup timer 0 as free-running clocksource */
 764        writel(0, timer3_va_base + TIMER_CTRL);
 765        writel(0xffffffff, timer3_va_base + TIMER_LOAD);
 766        writel(0xffffffff, timer3_va_base + TIMER_VALUE);
 767        writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
 768                timer3_va_base + TIMER_CTRL);
 769
 770        clocksource_realview.mult =
 771                clocksource_khz2mult(1000, clocksource_realview.shift);
 772        clocksource_register(&clocksource_realview);
 773}
 774
 775/*
 776 * Set up the clock source and clock events devices
 777 */
 778void __init realview_timer_init(unsigned int timer_irq)
 779{
 780        u32 val;
 781
 782        /* 
 783         * set clock frequency: 
 784         *      REALVIEW_REFCLK is 32KHz
 785         *      REALVIEW_TIMCLK is 1MHz
 786         */
 787        val = readl(__io_address(REALVIEW_SCTL_BASE));
 788        writel((REALVIEW_TIMCLK << REALVIEW_TIMER1_EnSel) |
 789               (REALVIEW_TIMCLK << REALVIEW_TIMER2_EnSel) | 
 790               (REALVIEW_TIMCLK << REALVIEW_TIMER3_EnSel) |
 791               (REALVIEW_TIMCLK << REALVIEW_TIMER4_EnSel) | val,
 792               __io_address(REALVIEW_SCTL_BASE));
 793
 794        /*
 795         * Initialise to a known state (all timers off)
 796         */
 797        writel(0, timer0_va_base + TIMER_CTRL);
 798        writel(0, timer1_va_base + TIMER_CTRL);
 799        writel(0, timer2_va_base + TIMER_CTRL);
 800        writel(0, timer3_va_base + TIMER_CTRL);
 801
 802        /* 
 803         * Make irqs happen for the system timer
 804         */
 805        setup_irq(timer_irq, &realview_timer_irq);
 806
 807        realview_clocksource_init();
 808        realview_clockevents_init(timer_irq);
 809}
 810
 811/*
 812 * Setup the memory banks.
 813 */
 814void realview_fixup(struct machine_desc *mdesc, struct tag *tags, char **from,
 815                    struct meminfo *meminfo)
 816{
 817        /*
 818         * Most RealView platforms have 512MB contiguous RAM at 0x70000000.
 819         * Half of this is mirrored at 0.
 820         */
 821#ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET
 822        meminfo->bank[0].start = 0x70000000;
 823        meminfo->bank[0].size = SZ_512M;
 824        meminfo->nr_banks = 1;
 825#else
 826        meminfo->bank[0].start = 0;
 827        meminfo->bank[0].size = SZ_256M;
 828        meminfo->nr_banks = 1;
 829#endif
 830}
 831