linux/arch/arm/mach-versatile/core.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/mach-versatile/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/config.h>
  22#include <linux/init.h>
  23#include <linux/device.h>
  24#include <linux/dma-mapping.h>
  25#include <linux/sysdev.h>
  26#include <linux/interrupt.h>
  27
  28#include <asm/system.h>
  29#include <asm/hardware.h>
  30#include <asm/io.h>
  31#include <asm/irq.h>
  32#include <asm/leds.h>
  33#include <asm/mach-types.h>
  34#include <asm/hardware/amba.h>
  35#include <asm/hardware/amba_clcd.h>
  36#include <asm/hardware/icst307.h>
  37
  38#include <asm/mach/arch.h>
  39#include <asm/mach/flash.h>
  40#include <asm/mach/irq.h>
  41#include <asm/mach/time.h>
  42#include <asm/mach/map.h>
  43#include <asm/mach/mmc.h>
  44
  45#include "core.h"
  46#include "clock.h"
  47
  48/*
  49 * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
  50 * is the (PA >> 12).
  51 *
  52 * Setup a VA for the Versatile Vectored Interrupt Controller.
  53 */
  54#define VA_VIC_BASE              IO_ADDRESS(VERSATILE_VIC_BASE)
  55#define VA_SIC_BASE              IO_ADDRESS(VERSATILE_SIC_BASE)
  56
  57static void vic_mask_irq(unsigned int irq)
  58{
  59        irq -= IRQ_VIC_START;
  60        writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR);
  61}
  62
  63static void vic_unmask_irq(unsigned int irq)
  64{
  65        irq -= IRQ_VIC_START;
  66        writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE);
  67}
  68
  69static struct irqchip vic_chip = {
  70        .ack    = vic_mask_irq,
  71        .mask   = vic_mask_irq,
  72        .unmask = vic_unmask_irq,
  73};
  74
  75static void sic_mask_irq(unsigned int irq)
  76{
  77        irq -= IRQ_SIC_START;
  78        writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
  79}
  80
  81static void sic_unmask_irq(unsigned int irq)
  82{
  83        irq -= IRQ_SIC_START;
  84        writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_SET);
  85}
  86
  87static struct irqchip sic_chip = {
  88        .ack    = sic_mask_irq,
  89        .mask   = sic_mask_irq,
  90        .unmask = sic_unmask_irq,
  91};
  92
  93static void
  94sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
  95{
  96        unsigned long status = readl(VA_SIC_BASE + SIC_IRQ_STATUS);
  97
  98        if (status == 0) {
  99                do_bad_IRQ(irq, desc, regs);
 100                return;
 101        }
 102
 103        do {
 104                irq = ffs(status) - 1;
 105                status &= ~(1 << irq);
 106
 107                irq += IRQ_SIC_START;
 108
 109                desc = irq_desc + irq;
 110                desc->handle(irq, desc, regs);
 111        } while (status);
 112}
 113
 114#if 1
 115#define IRQ_MMCI0A      IRQ_VICSOURCE22
 116#define IRQ_AACI        IRQ_VICSOURCE24
 117#define IRQ_ETH         IRQ_VICSOURCE25
 118#define PIC_MASK        0xFFD00000
 119#else
 120#define IRQ_MMCI0A      IRQ_SIC_MMCI0A
 121#define IRQ_AACI        IRQ_SIC_AACI
 122#define IRQ_ETH         IRQ_SIC_ETH
 123#define PIC_MASK        0
 124#endif
 125
 126void __init versatile_init_irq(void)
 127{
 128        unsigned int i, value;
 129
 130        /* Disable all interrupts initially. */
 131
 132        writel(0, VA_VIC_BASE + VIC_INT_SELECT);
 133        writel(0, VA_VIC_BASE + VIC_IRQ_ENABLE);
 134        writel(~0, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR);
 135        writel(0, VA_VIC_BASE + VIC_IRQ_STATUS);
 136        writel(0, VA_VIC_BASE + VIC_ITCR);
 137        writel(~0, VA_VIC_BASE + VIC_IRQ_SOFT_CLEAR);
 138
 139        /*
 140         * Make sure we clear all existing interrupts
 141         */
 142        writel(0, VA_VIC_BASE + VIC_VECT_ADDR);
 143        for (i = 0; i < 19; i++) {
 144                value = readl(VA_VIC_BASE + VIC_VECT_ADDR);
 145                writel(value, VA_VIC_BASE + VIC_VECT_ADDR);
 146        }
 147
 148        for (i = 0; i < 16; i++) {
 149                value = readl(VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4));
 150                writel(value | VICVectCntl_Enable | i, VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4));
 151        }
 152
 153        writel(32, VA_VIC_BASE + VIC_DEF_VECT_ADDR);
 154
 155        for (i = IRQ_VIC_START; i <= IRQ_VIC_END; i++) {
 156                if (i != IRQ_VICSOURCE31) {
 157                        set_irq_chip(i, &vic_chip);
 158                        set_irq_handler(i, do_level_IRQ);
 159                        set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 160                }
 161        }
 162
 163        set_irq_handler(IRQ_VICSOURCE31, sic_handle_irq);
 164        vic_unmask_irq(IRQ_VICSOURCE31);
 165
 166        /* Do second interrupt controller */
 167        writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
 168
 169        for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) {
 170                if ((PIC_MASK & (1 << (i - IRQ_SIC_START))) == 0) {
 171                        set_irq_chip(i, &sic_chip);
 172                        set_irq_handler(i, do_level_IRQ);
 173                        set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 174                }
 175        }
 176
 177        /*
 178         * Interrupts on secondary controller from 0 to 8 are routed to
 179         * source 31 on PIC.
 180         * Interrupts from 21 to 31 are routed directly to the VIC on
 181         * the corresponding number on primary controller. This is controlled
 182         * by setting PIC_ENABLEx.
 183         */
 184        writel(PIC_MASK, VA_SIC_BASE + SIC_INT_PIC_ENABLE);
 185}
 186
 187static struct map_desc versatile_io_desc[] __initdata = {
 188 { IO_ADDRESS(VERSATILE_SYS_BASE),   VERSATILE_SYS_BASE,   SZ_4K,      MT_DEVICE },
 189 { IO_ADDRESS(VERSATILE_SIC_BASE),   VERSATILE_SIC_BASE,   SZ_4K,      MT_DEVICE },
 190 { IO_ADDRESS(VERSATILE_VIC_BASE),   VERSATILE_VIC_BASE,   SZ_4K,      MT_DEVICE },
 191 { IO_ADDRESS(VERSATILE_SCTL_BASE),  VERSATILE_SCTL_BASE,  SZ_4K * 9,  MT_DEVICE },
 192#ifdef CONFIG_MACH_VERSATILE_AB
 193 { IO_ADDRESS(VERSATILE_GPIO0_BASE), VERSATILE_GPIO0_BASE, SZ_4K,      MT_DEVICE },
 194 { IO_ADDRESS(VERSATILE_IB2_BASE),   VERSATILE_IB2_BASE,   SZ_64M,     MT_DEVICE },
 195#endif
 196#ifdef CONFIG_DEBUG_LL
 197 { IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K,      MT_DEVICE },
 198#endif
 199#ifdef FIXME
 200 { PCI_MEMORY_VADDR,                 PHYS_PCI_MEM_BASE,    SZ_16M,     MT_DEVICE },
 201 { PCI_CONFIG_VADDR,                 PHYS_PCI_CONFIG_BASE, SZ_16M,     MT_DEVICE },
 202 { PCI_V3_VADDR,                     PHYS_PCI_V3_BASE,     SZ_512K,    MT_DEVICE },
 203 { PCI_IO_VADDR,                     PHYS_PCI_IO_BASE,     SZ_64K,     MT_DEVICE },
 204#endif
 205};
 206
 207void __init versatile_map_io(void)
 208{
 209        iotable_init(versatile_io_desc, ARRAY_SIZE(versatile_io_desc));
 210}
 211
 212#define VERSATILE_REFCOUNTER    (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET)
 213
 214/*
 215 * This is the Versatile sched_clock implementation.  This has
 216 * a resolution of 41.7ns, and a maximum value of about 179s.
 217 */
 218unsigned long long sched_clock(void)
 219{
 220        unsigned long long v;
 221
 222        v = (unsigned long long)readl(VERSATILE_REFCOUNTER) * 125;
 223        do_div(v, 3);
 224
 225        return v;
 226}
 227
 228
 229#define VERSATILE_FLASHCTRL    (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_FLASH_OFFSET)
 230
 231static int versatile_flash_init(void)
 232{
 233        u32 val;
 234
 235        val = __raw_readl(VERSATILE_FLASHCTRL);
 236        val &= ~VERSATILE_FLASHPROG_FLVPPEN;
 237        __raw_writel(val, VERSATILE_FLASHCTRL);
 238
 239        return 0;
 240}
 241
 242static void versatile_flash_exit(void)
 243{
 244        u32 val;
 245
 246        val = __raw_readl(VERSATILE_FLASHCTRL);
 247        val &= ~VERSATILE_FLASHPROG_FLVPPEN;
 248        __raw_writel(val, VERSATILE_FLASHCTRL);
 249}
 250
 251static void versatile_flash_set_vpp(int on)
 252{
 253        u32 val;
 254
 255        val = __raw_readl(VERSATILE_FLASHCTRL);
 256        if (on)
 257                val |= VERSATILE_FLASHPROG_FLVPPEN;
 258        else
 259                val &= ~VERSATILE_FLASHPROG_FLVPPEN;
 260        __raw_writel(val, VERSATILE_FLASHCTRL);
 261}
 262
 263static struct flash_platform_data versatile_flash_data = {
 264        .map_name               = "cfi_probe",
 265        .width                  = 4,
 266        .init                   = versatile_flash_init,
 267        .exit                   = versatile_flash_exit,
 268        .set_vpp                = versatile_flash_set_vpp,
 269};
 270
 271static struct resource versatile_flash_resource = {
 272        .start                  = VERSATILE_FLASH_BASE,
 273        .end                    = VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE,
 274        .flags                  = IORESOURCE_MEM,
 275};
 276
 277static struct platform_device versatile_flash_device = {
 278        .name                   = "armflash",
 279        .id                     = 0,
 280        .dev                    = {
 281                .platform_data  = &versatile_flash_data,
 282        },
 283        .num_resources          = 1,
 284        .resource               = &versatile_flash_resource,
 285};
 286
 287static struct resource smc91x_resources[] = {
 288        [0] = {
 289                .start          = VERSATILE_ETH_BASE,
 290                .end            = VERSATILE_ETH_BASE + SZ_64K - 1,
 291                .flags          = IORESOURCE_MEM,
 292        },
 293        [1] = {
 294                .start          = IRQ_ETH,
 295                .end            = IRQ_ETH,
 296                .flags          = IORESOURCE_IRQ,
 297        },
 298};
 299
 300static struct platform_device smc91x_device = {
 301        .name           = "smc91x",
 302        .id             = 0,
 303        .num_resources  = ARRAY_SIZE(smc91x_resources),
 304        .resource       = smc91x_resources,
 305};
 306
 307#define VERSATILE_SYSMCI        (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET)
 308
 309unsigned int mmc_status(struct device *dev)
 310{
 311        struct amba_device *adev = container_of(dev, struct amba_device, dev);
 312        u32 mask;
 313
 314        if (adev->res.start == VERSATILE_MMCI0_BASE)
 315                mask = 1;
 316        else
 317                mask = 2;
 318
 319        return readl(VERSATILE_SYSMCI) & mask;
 320}
 321
 322static struct mmc_platform_data mmc0_plat_data = {
 323        .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
 324        .status         = mmc_status,
 325};
 326
 327/*
 328 * Clock handling
 329 */
 330static const struct icst307_params versatile_oscvco_params = {
 331        .ref            = 24000,
 332        .vco_max        = 200000,
 333        .vd_min         = 4 + 8,
 334        .vd_max         = 511 + 8,
 335        .rd_min         = 1 + 2,
 336        .rd_max         = 127 + 2,
 337};
 338
 339static void versatile_oscvco_set(struct clk *clk, struct icst307_vco vco)
 340{
 341        unsigned long sys_lock = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_LOCK_OFFSET;
 342#if defined(CONFIG_ARCH_VERSATILE_PB)
 343        unsigned long sys_osc = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSC4_OFFSET;
 344#elif defined(CONFIG_MACH_VERSATILE_AB)
 345        unsigned long sys_osc = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSC1_OFFSET;
 346#endif
 347        u32 val;
 348
 349        val = readl(sys_osc) & ~0x7ffff;
 350        val |= vco.v | (vco.r << 9) | (vco.s << 16);
 351
 352        writel(0xa05f, sys_lock);
 353        writel(val, sys_osc);
 354        writel(0, sys_lock);
 355}
 356
 357static struct clk versatile_clcd_clk = {
 358        .name   = "CLCDCLK",
 359        .params = &versatile_oscvco_params,
 360        .setvco = versatile_oscvco_set,
 361};
 362
 363/*
 364 * CLCD support.
 365 */
 366#define SYS_CLCD_MODE_MASK      (3 << 0)
 367#define SYS_CLCD_MODE_888       (0 << 0)
 368#define SYS_CLCD_MODE_5551      (1 << 0)
 369#define SYS_CLCD_MODE_565_RLSB  (2 << 0)
 370#define SYS_CLCD_MODE_565_BLSB  (3 << 0)
 371#define SYS_CLCD_NLCDIOON       (1 << 2)
 372#define SYS_CLCD_VDDPOSSWITCH   (1 << 3)
 373#define SYS_CLCD_PWR3V5SWITCH   (1 << 4)
 374#define SYS_CLCD_ID_MASK        (0x1f << 8)
 375#define SYS_CLCD_ID_SANYO_3_8   (0x00 << 8)
 376#define SYS_CLCD_ID_UNKNOWN_8_4 (0x01 << 8)
 377#define SYS_CLCD_ID_EPSON_2_2   (0x02 << 8)
 378#define SYS_CLCD_ID_SANYO_2_5   (0x07 << 8)
 379#define SYS_CLCD_ID_VGA         (0x1f << 8)
 380
 381static struct clcd_panel vga = {
 382        .mode           = {
 383                .name           = "VGA",
 384                .refresh        = 60,
 385                .xres           = 640,
 386                .yres           = 480,
 387                .pixclock       = 39721,
 388                .left_margin    = 40,
 389                .right_margin   = 24,
 390                .upper_margin   = 32,
 391                .lower_margin   = 11,
 392                .hsync_len      = 96,
 393                .vsync_len      = 2,
 394                .sync           = 0,
 395                .vmode          = FB_VMODE_NONINTERLACED,
 396        },
 397        .width          = -1,
 398        .height         = -1,
 399        .tim2           = TIM2_BCD | TIM2_IPC,
 400        .cntl           = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
 401        .bpp            = 16,
 402};
 403
 404static struct clcd_panel sanyo_3_8_in = {
 405        .mode           = {
 406                .name           = "Sanyo QVGA",
 407                .refresh        = 116,
 408                .xres           = 320,
 409                .yres           = 240,
 410                .pixclock       = 100000,
 411                .left_margin    = 6,
 412                .right_margin   = 6,
 413                .upper_margin   = 5,
 414                .lower_margin   = 5,
 415                .hsync_len      = 6,
 416                .vsync_len      = 6,
 417                .sync           = 0,
 418                .vmode          = FB_VMODE_NONINTERLACED,
 419        },
 420        .width          = -1,
 421        .height         = -1,
 422        .tim2           = TIM2_BCD,
 423        .cntl           = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
 424        .bpp            = 16,
 425};
 426
 427static struct clcd_panel sanyo_2_5_in = {
 428        .mode           = {
 429                .name           = "Sanyo QVGA Portrait",
 430                .refresh        = 116,
 431                .xres           = 240,
 432                .yres           = 320,
 433                .pixclock       = 100000,
 434                .left_margin    = 20,
 435                .right_margin   = 10,
 436                .upper_margin   = 2,
 437                .lower_margin   = 2,
 438                .hsync_len      = 10,
 439                .vsync_len      = 2,
 440                .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
 441                .vmode          = FB_VMODE_NONINTERLACED,
 442        },
 443        .width          = -1,
 444        .height         = -1,
 445        .tim2           = TIM2_IVS | TIM2_IHS | TIM2_IPC,
 446        .cntl           = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
 447        .bpp            = 16,
 448};
 449
 450static struct clcd_panel epson_2_2_in = {
 451        .mode           = {
 452                .name           = "Epson QCIF",
 453                .refresh        = 390,
 454                .xres           = 176,
 455                .yres           = 220,
 456                .pixclock       = 62500,
 457                .left_margin    = 3,
 458                .right_margin   = 2,
 459                .upper_margin   = 1,
 460                .lower_margin   = 0,
 461                .hsync_len      = 3,
 462                .vsync_len      = 2,
 463                .sync           = 0,
 464                .vmode          = FB_VMODE_NONINTERLACED,
 465        },
 466        .width          = -1,
 467        .height         = -1,
 468        .tim2           = TIM2_BCD | TIM2_IPC,
 469        .cntl           = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
 470        .bpp            = 16,
 471};
 472
 473/*
 474 * Detect which LCD panel is connected, and return the appropriate
 475 * clcd_panel structure.  Note: we do not have any information on
 476 * the required timings for the 8.4in panel, so we presently assume
 477 * VGA timings.
 478 */
 479static struct clcd_panel *versatile_clcd_panel(void)
 480{
 481        unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
 482        struct clcd_panel *panel = &vga;
 483        u32 val;
 484
 485        val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
 486        if (val == SYS_CLCD_ID_SANYO_3_8)
 487                panel = &sanyo_3_8_in;
 488        else if (val == SYS_CLCD_ID_SANYO_2_5)
 489                panel = &sanyo_2_5_in;
 490        else if (val == SYS_CLCD_ID_EPSON_2_2)
 491                panel = &epson_2_2_in;
 492        else if (val == SYS_CLCD_ID_VGA)
 493                panel = &vga;
 494        else {
 495                printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
 496                        val);
 497                panel = &vga;
 498        }
 499
 500        return panel;
 501}
 502
 503/*
 504 * Disable all display connectors on the interface module.
 505 */
 506static void versatile_clcd_disable(struct clcd_fb *fb)
 507{
 508        unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
 509        u32 val;
 510
 511        val = readl(sys_clcd);
 512        val &= ~SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
 513        writel(val, sys_clcd);
 514
 515#ifdef CONFIG_MACH_VERSATILE_AB
 516        /*
 517         * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light off
 518         */
 519        if (fb->panel == &sanyo_2_5_in) {
 520                unsigned long versatile_ib2_ctrl = IO_ADDRESS(VERSATILE_IB2_CTRL);
 521                unsigned long ctrl;
 522
 523                ctrl = readl(versatile_ib2_ctrl);
 524                ctrl &= ~0x01;
 525                writel(ctrl, versatile_ib2_ctrl);
 526        }
 527#endif
 528}
 529
 530/*
 531 * Enable the relevant connector on the interface module.
 532 */
 533static void versatile_clcd_enable(struct clcd_fb *fb)
 534{
 535        unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
 536        u32 val;
 537
 538        val = readl(sys_clcd);
 539        val &= ~SYS_CLCD_MODE_MASK;
 540
 541        switch (fb->fb.var.green.length) {
 542        case 5:
 543                val |= SYS_CLCD_MODE_5551;
 544                break;
 545        case 6:
 546                val |= SYS_CLCD_MODE_565_BLSB;
 547                break;
 548        case 8:
 549                val |= SYS_CLCD_MODE_888;
 550                break;
 551        }
 552
 553        /*
 554         * Set the MUX
 555         */
 556        writel(val, sys_clcd);
 557
 558        /*
 559         * And now enable the PSUs
 560         */
 561        val |= SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
 562        writel(val, sys_clcd);
 563
 564#ifdef CONFIG_MACH_VERSATILE_AB
 565        /*
 566         * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light on
 567         */
 568        if (fb->panel == &sanyo_2_5_in) {
 569                unsigned long versatile_ib2_ctrl = IO_ADDRESS(VERSATILE_IB2_CTRL);
 570                unsigned long ctrl;
 571
 572                ctrl = readl(versatile_ib2_ctrl);
 573                ctrl |= 0x01;
 574                writel(ctrl, versatile_ib2_ctrl);
 575        }
 576#endif
 577}
 578
 579static unsigned long framesize = SZ_1M;
 580
 581static int versatile_clcd_setup(struct clcd_fb *fb)
 582{
 583        dma_addr_t dma;
 584
 585        fb->panel               = versatile_clcd_panel();
 586
 587        fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
 588                                                    &dma, GFP_KERNEL);
 589        if (!fb->fb.screen_base) {
 590                printk(KERN_ERR "CLCD: unable to map framebuffer\n");
 591                return -ENOMEM;
 592        }
 593
 594        fb->fb.fix.smem_start   = dma;
 595        fb->fb.fix.smem_len     = framesize;
 596
 597        return 0;
 598}
 599
 600static int versatile_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
 601{
 602        return dma_mmap_writecombine(&fb->dev->dev, vma,
 603                                     fb->fb.screen_base,
 604                                     fb->fb.fix.smem_start,
 605                                     fb->fb.fix.smem_len);
 606}
 607
 608static void versatile_clcd_remove(struct clcd_fb *fb)
 609{
 610        dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
 611                              fb->fb.screen_base, fb->fb.fix.smem_start);
 612}
 613
 614static struct clcd_board clcd_plat_data = {
 615        .name           = "Versatile",
 616        .check          = clcdfb_check,
 617        .decode         = clcdfb_decode,
 618        .disable        = versatile_clcd_disable,
 619        .enable         = versatile_clcd_enable,
 620        .setup          = versatile_clcd_setup,
 621        .mmap           = versatile_clcd_mmap,
 622        .remove         = versatile_clcd_remove,
 623};
 624
 625#define AACI_IRQ        { IRQ_AACI, NO_IRQ }
 626#define AACI_DMA        { 0x80, 0x81 }
 627#define MMCI0_IRQ       { IRQ_MMCI0A,IRQ_SIC_MMCI0B }
 628#define MMCI0_DMA       { 0x84, 0 }
 629#define KMI0_IRQ        { IRQ_SIC_KMI0, NO_IRQ }
 630#define KMI0_DMA        { 0, 0 }
 631#define KMI1_IRQ        { IRQ_SIC_KMI1, NO_IRQ }
 632#define KMI1_DMA        { 0, 0 }
 633
 634/*
 635 * These devices are connected directly to the multi-layer AHB switch
 636 */
 637#define SMC_IRQ         { NO_IRQ, NO_IRQ }
 638#define SMC_DMA         { 0, 0 }
 639#define MPMC_IRQ        { NO_IRQ, NO_IRQ }
 640#define MPMC_DMA        { 0, 0 }
 641#define CLCD_IRQ        { IRQ_CLCDINT, NO_IRQ }
 642#define CLCD_DMA        { 0, 0 }
 643#define DMAC_IRQ        { IRQ_DMAINT, NO_IRQ }
 644#define DMAC_DMA        { 0, 0 }
 645
 646/*
 647 * These devices are connected via the core APB bridge
 648 */
 649#define SCTL_IRQ        { NO_IRQ, NO_IRQ }
 650#define SCTL_DMA        { 0, 0 }
 651#define WATCHDOG_IRQ    { IRQ_WDOGINT, NO_IRQ }
 652#define WATCHDOG_DMA    { 0, 0 }
 653#define GPIO0_IRQ       { IRQ_GPIOINT0, NO_IRQ }
 654#define GPIO0_DMA       { 0, 0 }
 655#define GPIO1_IRQ       { IRQ_GPIOINT1, NO_IRQ }
 656#define GPIO1_DMA       { 0, 0 }
 657#define RTC_IRQ         { IRQ_RTCINT, NO_IRQ }
 658#define RTC_DMA         { 0, 0 }
 659
 660/*
 661 * These devices are connected via the DMA APB bridge
 662 */
 663#define SCI_IRQ         { IRQ_SCIINT, NO_IRQ }
 664#define SCI_DMA         { 7, 6 }
 665#define UART0_IRQ       { IRQ_UARTINT0, NO_IRQ }
 666#define UART0_DMA       { 15, 14 }
 667#define UART1_IRQ       { IRQ_UARTINT1, NO_IRQ }
 668#define UART1_DMA       { 13, 12 }
 669#define UART2_IRQ       { IRQ_UARTINT2, NO_IRQ }
 670#define UART2_DMA       { 11, 10 }
 671#define SSP_IRQ         { IRQ_SSPINT, NO_IRQ }
 672#define SSP_DMA         { 9, 8 }
 673
 674/* FPGA Primecells */
 675AMBA_DEVICE(aaci,  "fpga:04", AACI,     NULL);
 676AMBA_DEVICE(mmc0,  "fpga:05", MMCI0,    &mmc0_plat_data);
 677AMBA_DEVICE(kmi0,  "fpga:06", KMI0,     NULL);
 678AMBA_DEVICE(kmi1,  "fpga:07", KMI1,     NULL);
 679
 680/* DevChip Primecells */
 681AMBA_DEVICE(smc,   "dev:00",  SMC,      NULL);
 682AMBA_DEVICE(mpmc,  "dev:10",  MPMC,     NULL);
 683AMBA_DEVICE(clcd,  "dev:20",  CLCD,     &clcd_plat_data);
 684AMBA_DEVICE(dmac,  "dev:30",  DMAC,     NULL);
 685AMBA_DEVICE(sctl,  "dev:e0",  SCTL,     NULL);
 686AMBA_DEVICE(wdog,  "dev:e1",  WATCHDOG, NULL);
 687AMBA_DEVICE(gpio0, "dev:e4",  GPIO0,    NULL);
 688AMBA_DEVICE(gpio1, "dev:e5",  GPIO1,    NULL);
 689AMBA_DEVICE(rtc,   "dev:e8",  RTC,      NULL);
 690AMBA_DEVICE(sci0,  "dev:f0",  SCI,      NULL);
 691AMBA_DEVICE(uart0, "dev:f1",  UART0,    NULL);
 692AMBA_DEVICE(uart1, "dev:f2",  UART1,    NULL);
 693AMBA_DEVICE(uart2, "dev:f3",  UART2,    NULL);
 694AMBA_DEVICE(ssp0,  "dev:f4",  SSP,      NULL);
 695
 696static struct amba_device *amba_devs[] __initdata = {
 697        &dmac_device,
 698        &uart0_device,
 699        &uart1_device,
 700        &uart2_device,
 701        &smc_device,
 702        &mpmc_device,
 703        &clcd_device,
 704        &sctl_device,
 705        &wdog_device,
 706        &gpio0_device,
 707        &gpio1_device,
 708        &rtc_device,
 709        &sci0_device,
 710        &ssp0_device,
 711        &aaci_device,
 712        &mmc0_device,
 713        &kmi0_device,
 714        &kmi1_device,
 715};
 716
 717#ifdef CONFIG_LEDS
 718#define VA_LEDS_BASE (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET)
 719
 720static void versatile_leds_event(led_event_t ledevt)
 721{
 722        unsigned long flags;
 723        u32 val;
 724
 725        local_irq_save(flags);
 726        val = readl(VA_LEDS_BASE);
 727
 728        switch (ledevt) {
 729        case led_idle_start:
 730                val = val & ~VERSATILE_SYS_LED0;
 731                break;
 732
 733        case led_idle_end:
 734                val = val | VERSATILE_SYS_LED0;
 735                break;
 736
 737        case led_timer:
 738                val = val ^ VERSATILE_SYS_LED1;
 739                break;
 740
 741        case led_halted:
 742                val = 0;
 743                break;
 744
 745        default:
 746                break;
 747        }
 748
 749        writel(val, VA_LEDS_BASE);
 750        local_irq_restore(flags);
 751}
 752#endif  /* CONFIG_LEDS */
 753
 754void __init versatile_init(void)
 755{
 756        int i;
 757
 758        clk_register(&versatile_clcd_clk);
 759
 760        platform_device_register(&versatile_flash_device);
 761        platform_device_register(&smc91x_device);
 762
 763        for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
 764                struct amba_device *d = amba_devs[i];
 765                amba_device_register(d, &iomem_resource);
 766        }
 767
 768#ifdef CONFIG_LEDS
 769        leds_event = versatile_leds_event;
 770#endif
 771}
 772
 773/*
 774 * Where is the timer (VA)?
 775 */
 776#define TIMER0_VA_BASE           IO_ADDRESS(VERSATILE_TIMER0_1_BASE)
 777#define TIMER1_VA_BASE          (IO_ADDRESS(VERSATILE_TIMER0_1_BASE) + 0x20)
 778#define TIMER2_VA_BASE           IO_ADDRESS(VERSATILE_TIMER2_3_BASE)
 779#define TIMER3_VA_BASE          (IO_ADDRESS(VERSATILE_TIMER2_3_BASE) + 0x20)
 780#define VA_IC_BASE               IO_ADDRESS(VERSATILE_VIC_BASE) 
 781
 782/*
 783 * How long is the timer interval?
 784 */
 785#define TIMER_INTERVAL  (TICKS_PER_uSEC * mSEC_10)
 786#if TIMER_INTERVAL >= 0x100000
 787#define TIMER_RELOAD    (TIMER_INTERVAL >> 8)           /* Divide by 256 */
 788#define TIMER_CTRL      0x88                            /* Enable, Clock / 256 */
 789#define TICKS2USECS(x)  (256 * (x) / TICKS_PER_uSEC)
 790#elif TIMER_INTERVAL >= 0x10000
 791#define TIMER_RELOAD    (TIMER_INTERVAL >> 4)           /* Divide by 16 */
 792#define TIMER_CTRL      0x84                            /* Enable, Clock / 16 */
 793#define TICKS2USECS(x)  (16 * (x) / TICKS_PER_uSEC)
 794#else
 795#define TIMER_RELOAD    (TIMER_INTERVAL)
 796#define TIMER_CTRL      0x80                            /* Enable */
 797#define TICKS2USECS(x)  ((x) / TICKS_PER_uSEC)
 798#endif
 799
 800#define TIMER_CTRL_IE   (1 << 5)        /* Interrupt Enable */
 801
 802/*
 803 * What does it look like?
 804 */
 805typedef struct TimerStruct {
 806        unsigned long TimerLoad;
 807        unsigned long TimerValue;
 808        unsigned long TimerControl;
 809        unsigned long TimerClear;
 810} TimerStruct_t;
 811
 812/*
 813 * Returns number of ms since last clock interrupt.  Note that interrupts
 814 * will have been disabled by do_gettimeoffset()
 815 */
 816static unsigned long versatile_gettimeoffset(void)
 817{
 818        volatile TimerStruct_t *timer0 = (TimerStruct_t *)TIMER0_VA_BASE;
 819        unsigned long ticks1, ticks2, status;
 820
 821        /*
 822         * Get the current number of ticks.  Note that there is a race
 823         * condition between us reading the timer and checking for
 824         * an interrupt.  We get around this by ensuring that the
 825         * counter has not reloaded between our two reads.
 826         */
 827        ticks2 = timer0->TimerValue & 0xffff;
 828        do {
 829                ticks1 = ticks2;
 830                status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS);
 831                ticks2 = timer0->TimerValue & 0xffff;
 832        } while (ticks2 > ticks1);
 833
 834        /*
 835         * Number of ticks since last interrupt.
 836         */
 837        ticks1 = TIMER_RELOAD - ticks2;
 838
 839        /*
 840         * Interrupt pending?  If so, we've reloaded once already.
 841         *
 842         * FIXME: Need to check this is effectively timer 0 that expires
 843         */
 844        if (status & IRQMASK_TIMERINT0_1)
 845                ticks1 += TIMER_RELOAD;
 846
 847        /*
 848         * Convert the ticks to usecs
 849         */
 850        return TICKS2USECS(ticks1);
 851}
 852
 853/*
 854 * IRQ handler for the timer
 855 */
 856static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 857{
 858        volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
 859
 860        write_seqlock(&xtime_lock);
 861
 862        // ...clear the interrupt
 863        timer0->TimerClear = 1;
 864
 865        timer_tick(regs);
 866
 867        write_sequnlock(&xtime_lock);
 868
 869        return IRQ_HANDLED;
 870}
 871
 872static struct irqaction versatile_timer_irq = {
 873        .name           = "Versatile Timer Tick",
 874        .flags          = SA_INTERRUPT,
 875        .handler        = versatile_timer_interrupt
 876};
 877
 878/*
 879 * Set up timer interrupt, and return the current time in seconds.
 880 */
 881static void __init versatile_timer_init(void)
 882{
 883        volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
 884        volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
 885        volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE;
 886        volatile TimerStruct_t *timer3 = (volatile TimerStruct_t *)TIMER3_VA_BASE;
 887
 888        /* 
 889         * set clock frequency: 
 890         *      VERSATILE_REFCLK is 32KHz
 891         *      VERSATILE_TIMCLK is 1MHz
 892         */
 893        *(volatile unsigned int *)IO_ADDRESS(VERSATILE_SCTL_BASE) |= 
 894          ((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | 
 895           (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel));
 896
 897        /*
 898         * Initialise to a known state (all timers off)
 899         */
 900        timer0->TimerControl = 0;
 901        timer1->TimerControl = 0;
 902        timer2->TimerControl = 0;
 903        timer3->TimerControl = 0;
 904
 905        timer0->TimerLoad    = TIMER_RELOAD;
 906        timer0->TimerValue   = TIMER_RELOAD;
 907        timer0->TimerControl = TIMER_CTRL | 0x40 | TIMER_CTRL_IE;  /* periodic + IE */
 908
 909        /* 
 910         * Make irqs happen for the system timer
 911         */
 912        setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq);
 913}
 914
 915struct sys_timer versatile_timer = {
 916        .init           = versatile_timer_init,
 917        .offset         = versatile_gettimeoffset,
 918};
 919
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.