linux/arch/arm/mach-integrator/integrator_ap.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/mach-integrator/integrator_ap.c
   3 *
   4 *  Copyright (C) 2000-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, or
   9 * (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19 */
  20#include <linux/types.h>
  21#include <linux/kernel.h>
  22#include <linux/init.h>
  23#include <linux/list.h>
  24#include <linux/platform_device.h>
  25#include <linux/slab.h>
  26#include <linux/string.h>
  27#include <linux/sysdev.h>
  28#include <linux/amba/bus.h>
  29#include <linux/amba/kmi.h>
  30#include <linux/io.h>
  31
  32#include <mach/hardware.h>
  33#include <asm/irq.h>
  34#include <asm/setup.h>
  35#include <asm/param.h>          /* HZ */
  36#include <asm/mach-types.h>
  37
  38#include <mach/lm.h>
  39
  40#include <asm/mach/arch.h>
  41#include <asm/mach/flash.h>
  42#include <asm/mach/irq.h>
  43#include <asm/mach/map.h>
  44#include <asm/mach/time.h>
  45
  46#include "common.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 Integrator interrupt controller (for header #0,
  53 * just for now).
  54 */
  55#define VA_IC_BASE      IO_ADDRESS(INTEGRATOR_IC_BASE) 
  56#define VA_SC_BASE      IO_ADDRESS(INTEGRATOR_SC_BASE)
  57#define VA_EBI_BASE     IO_ADDRESS(INTEGRATOR_EBI_BASE)
  58#define VA_CMIC_BASE    IO_ADDRESS(INTEGRATOR_HDR_BASE) + INTEGRATOR_HDR_IC_OFFSET
  59
  60/*
  61 * Logical      Physical
  62 * e8000000     40000000        PCI memory              PHYS_PCI_MEM_BASE       (max 512M)
  63 * ec000000     61000000        PCI config space        PHYS_PCI_CONFIG_BASE    (max 16M)
  64 * ed000000     62000000        PCI V3 regs             PHYS_PCI_V3_BASE        (max 64k)
  65 * ee000000     60000000        PCI IO                  PHYS_PCI_IO_BASE        (max 16M)
  66 * ef000000                     Cache flush
  67 * f1000000     10000000        Core module registers
  68 * f1100000     11000000        System controller registers
  69 * f1200000     12000000        EBI registers
  70 * f1300000     13000000        Counter/Timer
  71 * f1400000     14000000        Interrupt controller
  72 * f1600000     16000000        UART 0
  73 * f1700000     17000000        UART 1
  74 * f1a00000     1a000000        Debug LEDs
  75 * f1b00000     1b000000        GPIO
  76 */
  77
  78static struct map_desc ap_io_desc[] __initdata = {
  79        {
  80                .virtual        = IO_ADDRESS(INTEGRATOR_HDR_BASE),
  81                .pfn            = __phys_to_pfn(INTEGRATOR_HDR_BASE),
  82                .length         = SZ_4K,
  83                .type           = MT_DEVICE
  84        }, {
  85                .virtual        = IO_ADDRESS(INTEGRATOR_SC_BASE),
  86                .pfn            = __phys_to_pfn(INTEGRATOR_SC_BASE),
  87                .length         = SZ_4K,
  88                .type           = MT_DEVICE
  89        }, {
  90                .virtual        = IO_ADDRESS(INTEGRATOR_EBI_BASE),
  91                .pfn            = __phys_to_pfn(INTEGRATOR_EBI_BASE),
  92                .length         = SZ_4K,
  93                .type           = MT_DEVICE
  94        }, {
  95                .virtual        = IO_ADDRESS(INTEGRATOR_CT_BASE),
  96                .pfn            = __phys_to_pfn(INTEGRATOR_CT_BASE),
  97                .length         = SZ_4K,
  98                .type           = MT_DEVICE
  99        }, {
 100                .virtual        = IO_ADDRESS(INTEGRATOR_IC_BASE),
 101                .pfn            = __phys_to_pfn(INTEGRATOR_IC_BASE),
 102                .length         = SZ_4K,
 103                .type           = MT_DEVICE
 104        }, {
 105                .virtual        = IO_ADDRESS(INTEGRATOR_UART0_BASE),
 106                .pfn            = __phys_to_pfn(INTEGRATOR_UART0_BASE),
 107                .length         = SZ_4K,
 108                .type           = MT_DEVICE
 109        }, {
 110                .virtual        = IO_ADDRESS(INTEGRATOR_UART1_BASE),
 111                .pfn            = __phys_to_pfn(INTEGRATOR_UART1_BASE),
 112                .length         = SZ_4K,
 113                .type           = MT_DEVICE
 114        }, {
 115                .virtual        = IO_ADDRESS(INTEGRATOR_DBG_BASE),
 116                .pfn            = __phys_to_pfn(INTEGRATOR_DBG_BASE),
 117                .length         = SZ_4K,
 118                .type           = MT_DEVICE
 119        }, {
 120                .virtual        = IO_ADDRESS(INTEGRATOR_GPIO_BASE),
 121                .pfn            = __phys_to_pfn(INTEGRATOR_GPIO_BASE),
 122                .length         = SZ_4K,
 123                .type           = MT_DEVICE
 124        }, {
 125                .virtual        = PCI_MEMORY_VADDR,
 126                .pfn            = __phys_to_pfn(PHYS_PCI_MEM_BASE),
 127                .length         = SZ_16M,
 128                .type           = MT_DEVICE
 129        }, {
 130                .virtual        = PCI_CONFIG_VADDR,
 131                .pfn            = __phys_to_pfn(PHYS_PCI_CONFIG_BASE),
 132                .length         = SZ_16M,
 133                .type           = MT_DEVICE
 134        }, {
 135                .virtual        = PCI_V3_VADDR,
 136                .pfn            = __phys_to_pfn(PHYS_PCI_V3_BASE),
 137                .length         = SZ_64K,
 138                .type           = MT_DEVICE
 139        }, {
 140                .virtual        = PCI_IO_VADDR,
 141                .pfn            = __phys_to_pfn(PHYS_PCI_IO_BASE),
 142                .length         = SZ_64K,
 143                .type           = MT_DEVICE
 144        }
 145};
 146
 147static void __init ap_map_io(void)
 148{
 149        iotable_init(ap_io_desc, ARRAY_SIZE(ap_io_desc));
 150}
 151
 152#define INTEGRATOR_SC_VALID_INT 0x003fffff
 153
 154static void sc_mask_irq(unsigned int irq)
 155{
 156        writel(1 << irq, VA_IC_BASE + IRQ_ENABLE_CLEAR);
 157}
 158
 159static void sc_unmask_irq(unsigned int irq)
 160{
 161        writel(1 << irq, VA_IC_BASE + IRQ_ENABLE_SET);
 162}
 163
 164static struct irq_chip sc_chip = {
 165        .name   = "SC",
 166        .ack    = sc_mask_irq,
 167        .mask   = sc_mask_irq,
 168        .unmask = sc_unmask_irq,
 169};
 170
 171static void __init ap_init_irq(void)
 172{
 173        unsigned int i;
 174
 175        /* Disable all interrupts initially. */
 176        /* Do the core module ones */
 177        writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
 178
 179        /* do the header card stuff next */
 180        writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
 181        writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
 182
 183        for (i = 0; i < NR_IRQS; i++) {
 184                if (((1 << i) & INTEGRATOR_SC_VALID_INT) != 0) {
 185                        set_irq_chip(i, &sc_chip);
 186                        set_irq_handler(i, handle_level_irq);
 187                        set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 188                }
 189        }
 190}
 191
 192#ifdef CONFIG_PM
 193static unsigned long ic_irq_enable;
 194
 195static int irq_suspend(struct sys_device *dev, pm_message_t state)
 196{
 197        ic_irq_enable = readl(VA_IC_BASE + IRQ_ENABLE);
 198        return 0;
 199}
 200
 201static int irq_resume(struct sys_device *dev)
 202{
 203        /* disable all irq sources */
 204        writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
 205        writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
 206        writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
 207
 208        writel(ic_irq_enable, VA_IC_BASE + IRQ_ENABLE_SET);
 209        return 0;
 210}
 211#else
 212#define irq_suspend NULL
 213#define irq_resume NULL
 214#endif
 215
 216static struct sysdev_class irq_class = {
 217        .name           = "irq",
 218        .suspend        = irq_suspend,
 219        .resume         = irq_resume,
 220};
 221
 222static struct sys_device irq_device = {
 223        .id     = 0,
 224        .cls    = &irq_class,
 225};
 226
 227static int __init irq_init_sysfs(void)
 228{
 229        int ret = sysdev_class_register(&irq_class);
 230        if (ret == 0)
 231                ret = sysdev_register(&irq_device);
 232        return ret;
 233}
 234
 235device_initcall(irq_init_sysfs);
 236
 237/*
 238 * Flash handling.
 239 */
 240#define SC_CTRLC (VA_SC_BASE + INTEGRATOR_SC_CTRLC_OFFSET)
 241#define SC_CTRLS (VA_SC_BASE + INTEGRATOR_SC_CTRLS_OFFSET)
 242#define EBI_CSR1 (VA_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET)
 243#define EBI_LOCK (VA_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET)
 244
 245static int ap_flash_init(void)
 246{
 247        u32 tmp;
 248
 249        writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
 250
 251        tmp = readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE;
 252        writel(tmp, EBI_CSR1);
 253
 254        if (!(readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) {
 255                writel(0xa05f, EBI_LOCK);
 256                writel(tmp, EBI_CSR1);
 257                writel(0, EBI_LOCK);
 258        }
 259        return 0;
 260}
 261
 262static void ap_flash_exit(void)
 263{
 264        u32 tmp;
 265
 266        writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
 267
 268        tmp = readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE;
 269        writel(tmp, EBI_CSR1);
 270
 271        if (readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) {
 272                writel(0xa05f, EBI_LOCK);
 273                writel(tmp, EBI_CSR1);
 274                writel(0, EBI_LOCK);
 275        }
 276}
 277
 278static void ap_flash_set_vpp(int on)
 279{
 280        unsigned long reg = on ? SC_CTRLS : SC_CTRLC;
 281
 282        writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg);
 283}
 284
 285static struct flash_platform_data ap_flash_data = {
 286        .map_name       = "cfi_probe",
 287        .width          = 4,
 288        .init           = ap_flash_init,
 289        .exit           = ap_flash_exit,
 290        .set_vpp        = ap_flash_set_vpp,
 291};
 292
 293static struct resource cfi_flash_resource = {
 294        .start          = INTEGRATOR_FLASH_BASE,
 295        .end            = INTEGRATOR_FLASH_BASE + INTEGRATOR_FLASH_SIZE - 1,
 296        .flags          = IORESOURCE_MEM,
 297};
 298
 299static struct platform_device cfi_flash_device = {
 300        .name           = "armflash",
 301        .id             = 0,
 302        .dev            = {
 303                .platform_data  = &ap_flash_data,
 304        },
 305        .num_resources  = 1,
 306        .resource       = &cfi_flash_resource,
 307};
 308
 309static void __init ap_init(void)
 310{
 311        unsigned long sc_dec;
 312        int i;
 313
 314        platform_device_register(&cfi_flash_device);
 315
 316        sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
 317        for (i = 0; i < 4; i++) {
 318                struct lm_device *lmdev;
 319
 320                if ((sc_dec & (16 << i)) == 0)
 321                        continue;
 322
 323                lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL);
 324                if (!lmdev)
 325                        continue;
 326
 327                lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
 328                lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
 329                lmdev->resource.flags = IORESOURCE_MEM;
 330                lmdev->irq = IRQ_AP_EXPINT0 + i;
 331                lmdev->id = i;
 332
 333                lm_device_register(lmdev);
 334        }
 335}
 336
 337static void __init ap_init_timer(void)
 338{
 339        integrator_time_init(1000000 * TICKS_PER_uSEC / HZ, 0);
 340}
 341
 342static struct sys_timer ap_timer = {
 343        .init           = ap_init_timer,
 344        .offset         = integrator_gettimeoffset,
 345};
 346
 347MACHINE_START(INTEGRATOR, "ARM-Integrator")
 348        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 349        .phys_io        = 0x16000000,
 350        .io_pg_offst    = ((0xf1600000) >> 18) & 0xfffc,
 351        .boot_params    = 0x00000100,
 352        .map_io         = ap_map_io,
 353        .init_irq       = ap_init_irq,
 354        .timer          = &ap_timer,
 355        .init_machine   = ap_init,
 356MACHINE_END
 357