linux/arch/mips/sni/pcit.c
<<
>>
Prefs
   1/*
   2 * PCI Tower specific code
   3 *
   4 * This file is subject to the terms and conditions of the GNU General Public
   5 * License.  See the file "COPYING" in the main directory of this archive
   6 * for more details.
   7 *
   8 * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
   9 */
  10
  11#include <linux/init.h>
  12#include <linux/interrupt.h>
  13#include <linux/pci.h>
  14#include <linux/serial_8250.h>
  15
  16#include <asm/sni.h>
  17#include <asm/time.h>
  18#include <asm/irq_cpu.h>
  19
  20
  21#define PORT(_base,_irq)                                \
  22        {                                               \
  23                .iobase         = _base,                \
  24                .irq            = _irq,                 \
  25                .uartclk        = 1843200,              \
  26                .iotype         = UPIO_PORT,            \
  27                .flags          = UPF_BOOT_AUTOCONF,    \
  28        }
  29
  30static struct plat_serial8250_port pcit_data[] = {
  31        PORT(0x3f8, 0),
  32        PORT(0x2f8, 3),
  33        { },
  34};
  35
  36static struct platform_device pcit_serial8250_device = {
  37        .name                   = "serial8250",
  38        .id                     = PLAT8250_DEV_PLATFORM,
  39        .dev                    = {
  40                .platform_data  = pcit_data,
  41        },
  42};
  43
  44static struct plat_serial8250_port pcit_cplus_data[] = {
  45        PORT(0x3f8, 0),
  46        PORT(0x2f8, 3),
  47        PORT(0x3e8, 4),
  48        PORT(0x2e8, 3),
  49        { },
  50};
  51
  52static struct platform_device pcit_cplus_serial8250_device = {
  53        .name                   = "serial8250",
  54        .id                     = PLAT8250_DEV_PLATFORM,
  55        .dev                    = {
  56                .platform_data  = pcit_cplus_data,
  57        },
  58};
  59
  60static struct resource pcit_cmos_rsrc[] = {
  61        {
  62                .start = 0x70,
  63                .end   = 0x71,
  64                .flags = IORESOURCE_IO
  65        },
  66        {
  67                .start = 8,
  68                .end   = 8,
  69                .flags = IORESOURCE_IRQ
  70        }
  71};
  72
  73static struct platform_device pcit_cmos_device = {
  74        .name           = "rtc_cmos",
  75        .num_resources  = ARRAY_SIZE(pcit_cmos_rsrc),
  76        .resource       = pcit_cmos_rsrc
  77};
  78
  79static struct platform_device pcit_pcspeaker_pdev = {
  80        .name           = "pcspkr",
  81        .id             = -1,
  82};
  83
  84static struct resource sni_io_resource = {
  85        .start  = 0x00000000UL,
  86        .end    = 0x03bfffffUL,
  87        .name   = "PCIT IO",
  88        .flags  = IORESOURCE_IO,
  89};
  90
  91static struct resource pcit_io_resources[] = {
  92        {
  93                .start  = 0x00,
  94                .end    = 0x1f,
  95                .name   = "dma1",
  96                .flags  = IORESOURCE_BUSY
  97        }, {
  98                .start  =  0x40,
  99                .end    = 0x5f,
 100                .name   = "timer",
 101                .flags  = IORESOURCE_BUSY
 102        }, {
 103                .start  =  0x60,
 104                .end    = 0x6f,
 105                .name   = "keyboard",
 106                .flags  = IORESOURCE_BUSY
 107        }, {
 108                .start  =  0x80,
 109                .end    = 0x8f,
 110                .name   = "dma page reg",
 111                .flags  = IORESOURCE_BUSY
 112        }, {
 113                .start  =  0xc0,
 114                .end    = 0xdf,
 115                .name   = "dma2",
 116                .flags  = IORESOURCE_BUSY
 117        }, {
 118                .start  =  0xcf8,
 119                .end    = 0xcfb,
 120                .name   = "PCI config addr",
 121                .flags  = IORESOURCE_BUSY
 122        }, {
 123                .start  =  0xcfc,
 124                .end    = 0xcff,
 125                .name   = "PCI config data",
 126                .flags  = IORESOURCE_BUSY
 127        }
 128};
 129
 130static struct resource sni_mem_resource = {
 131        .start  = 0x18000000UL,
 132        .end    = 0x1fbfffffUL,
 133        .name   = "PCIT PCI MEM",
 134        .flags  = IORESOURCE_MEM
 135};
 136
 137static void __init sni_pcit_resource_init(void)
 138{
 139        int i;
 140
 141        /* request I/O space for devices used on all i[345]86 PCs */
 142        for (i = 0; i < ARRAY_SIZE(pcit_io_resources); i++)
 143                request_resource(&sni_io_resource, pcit_io_resources + i);
 144}
 145
 146
 147extern struct pci_ops sni_pcit_ops;
 148
 149static struct pci_controller sni_pcit_controller = {
 150        .pci_ops        = &sni_pcit_ops,
 151        .mem_resource   = &sni_mem_resource,
 152        .mem_offset     = 0x00000000UL,
 153        .io_resource    = &sni_io_resource,
 154        .io_offset      = 0x00000000UL,
 155        .io_map_base    = SNI_PORT_BASE
 156};
 157
 158static void enable_pcit_irq(unsigned int irq)
 159{
 160        u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24);
 161
 162        *(volatile u32 *)SNI_PCIT_INT_REG |= mask;
 163}
 164
 165void disable_pcit_irq(unsigned int irq)
 166{
 167        u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24);
 168
 169        *(volatile u32 *)SNI_PCIT_INT_REG &= ~mask;
 170}
 171
 172void end_pcit_irq(unsigned int irq)
 173{
 174        if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 175                enable_pcit_irq(irq);
 176}
 177
 178static struct irq_chip pcit_irq_type = {
 179        .typename = "PCIT",
 180        .ack = disable_pcit_irq,
 181        .mask = disable_pcit_irq,
 182        .mask_ack = disable_pcit_irq,
 183        .unmask = enable_pcit_irq,
 184        .end = end_pcit_irq,
 185};
 186
 187static void pcit_hwint1(void)
 188{
 189        u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG;
 190        int irq;
 191
 192        clear_c0_status(IE_IRQ1);
 193        irq = ffs((pending >> 16) & 0x7f);
 194
 195        if (likely(irq > 0))
 196                do_IRQ(irq + SNI_PCIT_INT_START - 1);
 197        set_c0_status(IE_IRQ1);
 198}
 199
 200static void pcit_hwint0(void)
 201{
 202        u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG;
 203        int irq;
 204
 205        clear_c0_status(IE_IRQ0);
 206        irq = ffs((pending >> 16) & 0x3f);
 207
 208        if (likely(irq > 0))
 209                do_IRQ(irq + SNI_PCIT_INT_START - 1);
 210        set_c0_status(IE_IRQ0);
 211}
 212
 213static void sni_pcit_hwint(void)
 214{
 215        u32 pending = read_c0_cause() & read_c0_status();
 216
 217        if (pending & C_IRQ1)
 218                pcit_hwint1();
 219        else if (pending & C_IRQ2)
 220                do_IRQ(MIPS_CPU_IRQ_BASE + 4);
 221        else if (pending & C_IRQ3)
 222                do_IRQ(MIPS_CPU_IRQ_BASE + 5);
 223        else if (pending & C_IRQ5)
 224                do_IRQ(MIPS_CPU_IRQ_BASE + 7);
 225}
 226
 227static void sni_pcit_hwint_cplus(void)
 228{
 229        u32 pending = read_c0_cause() & read_c0_status();
 230
 231        if (pending & C_IRQ0)
 232                pcit_hwint0();
 233        else if (pending & C_IRQ1)
 234                do_IRQ(MIPS_CPU_IRQ_BASE + 3);
 235        else if (pending & C_IRQ2)
 236                do_IRQ(MIPS_CPU_IRQ_BASE + 4);
 237        else if (pending & C_IRQ3)
 238                do_IRQ(MIPS_CPU_IRQ_BASE + 5);
 239        else if (pending & C_IRQ5)
 240                do_IRQ(MIPS_CPU_IRQ_BASE + 7);
 241}
 242
 243void __init sni_pcit_irq_init(void)
 244{
 245        int i;
 246
 247        mips_cpu_irq_init();
 248        for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
 249                set_irq_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
 250        *(volatile u32 *)SNI_PCIT_INT_REG = 0;
 251        sni_hwint = sni_pcit_hwint;
 252        change_c0_status(ST0_IM, IE_IRQ1);
 253        setup_irq(SNI_PCIT_INT_START + 6, &sni_isa_irq);
 254}
 255
 256void __init sni_pcit_cplus_irq_init(void)
 257{
 258        int i;
 259
 260        mips_cpu_irq_init();
 261        for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
 262                set_irq_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
 263        *(volatile u32 *)SNI_PCIT_INT_REG = 0x40000000;
 264        sni_hwint = sni_pcit_hwint_cplus;
 265        change_c0_status(ST0_IM, IE_IRQ0);
 266        setup_irq(MIPS_CPU_IRQ_BASE + 3, &sni_isa_irq);
 267}
 268
 269void __init sni_pcit_init(void)
 270{
 271        ioport_resource.end = sni_io_resource.end;
 272#ifdef CONFIG_PCI
 273        PCIBIOS_MIN_IO = 0x9000;
 274        register_pci_controller(&sni_pcit_controller);
 275#endif
 276        sni_pcit_resource_init();
 277}
 278
 279static int __init snirm_pcit_setup_devinit(void)
 280{
 281        switch (sni_brd_type) {
 282        case SNI_BRD_PCI_TOWER:
 283                platform_device_register(&pcit_serial8250_device);
 284                platform_device_register(&pcit_cmos_device);
 285                platform_device_register(&pcit_pcspeaker_pdev);
 286                break;
 287
 288        case SNI_BRD_PCI_TOWER_CPLUS:
 289                platform_device_register(&pcit_cplus_serial8250_device);
 290                platform_device_register(&pcit_cmos_device);
 291                platform_device_register(&pcit_pcspeaker_pdev);
 292                break;
 293        }
 294        return 0;
 295}
 296
 297device_initcall(snirm_pcit_setup_devinit);
 298