linux/arch/alpha/kernel/sys_titan.c
<<
>>
Prefs
   1/*
   2 *      linux/arch/alpha/kernel/sys_titan.c
   3 *
   4 *      Copyright (C) 1995 David A Rusling
   5 *      Copyright (C) 1996, 1999 Jay A Estabrook
   6 *      Copyright (C) 1998, 1999 Richard Henderson
   7 *      Copyright (C) 1999, 2000 Jeff Wiedemeier
   8 *
   9 * Code supporting TITAN systems (EV6+TITAN), currently:
  10 *      Privateer
  11 *      Falcon
  12 *      Granite
  13 */
  14
  15#include <linux/kernel.h>
  16#include <linux/types.h>
  17#include <linux/mm.h>
  18#include <linux/sched.h>
  19#include <linux/pci.h>
  20#include <linux/init.h>
  21#include <linux/bitops.h>
  22
  23#include <asm/ptrace.h>
  24#include <asm/system.h>
  25#include <asm/dma.h>
  26#include <asm/irq.h>
  27#include <asm/mmu_context.h>
  28#include <asm/io.h>
  29#include <asm/pgtable.h>
  30#include <asm/core_titan.h>
  31#include <asm/hwrpb.h>
  32#include <asm/tlbflush.h>
  33
  34#include "proto.h"
  35#include "irq_impl.h"
  36#include "pci_impl.h"
  37#include "machvec_impl.h"
  38#include "err_impl.h"
  39
  40
  41/*
  42 * Titan generic
  43 */
  44
  45/*
  46 * Titan supports up to 4 CPUs
  47 */
  48static unsigned long titan_cpu_irq_affinity[4] = { ~0UL, ~0UL, ~0UL, ~0UL };
  49
  50/*
  51 * Mask is set (1) if enabled
  52 */
  53static unsigned long titan_cached_irq_mask;
  54
  55/*
  56 * Need SMP-safe access to interrupt CSRs
  57 */
  58DEFINE_SPINLOCK(titan_irq_lock);
  59
  60static void
  61titan_update_irq_hw(unsigned long mask)
  62{
  63        register titan_cchip *cchip = TITAN_cchip;
  64        unsigned long isa_enable = 1UL << 55;
  65        register int bcpu = boot_cpuid;
  66
  67#ifdef CONFIG_SMP
  68        cpumask_t cpm = cpu_present_map;
  69        volatile unsigned long *dim0, *dim1, *dim2, *dim3;
  70        unsigned long mask0, mask1, mask2, mask3, dummy;
  71
  72        mask &= ~isa_enable;
  73        mask0 = mask & titan_cpu_irq_affinity[0];
  74        mask1 = mask & titan_cpu_irq_affinity[1];
  75        mask2 = mask & titan_cpu_irq_affinity[2];
  76        mask3 = mask & titan_cpu_irq_affinity[3];
  77
  78        if (bcpu == 0) mask0 |= isa_enable;
  79        else if (bcpu == 1) mask1 |= isa_enable;
  80        else if (bcpu == 2) mask2 |= isa_enable;
  81        else mask3 |= isa_enable;
  82
  83        dim0 = &cchip->dim0.csr;
  84        dim1 = &cchip->dim1.csr;
  85        dim2 = &cchip->dim2.csr;
  86        dim3 = &cchip->dim3.csr;
  87        if (!cpu_isset(0, cpm)) dim0 = &dummy;
  88        if (!cpu_isset(1, cpm)) dim1 = &dummy;
  89        if (!cpu_isset(2, cpm)) dim2 = &dummy;
  90        if (!cpu_isset(3, cpm)) dim3 = &dummy;
  91
  92        *dim0 = mask0;
  93        *dim1 = mask1;
  94        *dim2 = mask2;
  95        *dim3 = mask3;
  96        mb();
  97        *dim0;
  98        *dim1;
  99        *dim2;
 100        *dim3;
 101#else
 102        volatile unsigned long *dimB;
 103        dimB = &cchip->dim0.csr;
 104        if (bcpu == 1) dimB = &cchip->dim1.csr;
 105        else if (bcpu == 2) dimB = &cchip->dim2.csr;
 106        else if (bcpu == 3) dimB = &cchip->dim3.csr;
 107
 108        *dimB = mask | isa_enable;
 109        mb();
 110        *dimB;
 111#endif
 112}
 113
 114static inline void
 115titan_enable_irq(unsigned int irq)
 116{
 117        spin_lock(&titan_irq_lock);
 118        titan_cached_irq_mask |= 1UL << (irq - 16);
 119        titan_update_irq_hw(titan_cached_irq_mask);
 120        spin_unlock(&titan_irq_lock);
 121}
 122
 123static inline void
 124titan_disable_irq(unsigned int irq)
 125{
 126        spin_lock(&titan_irq_lock);
 127        titan_cached_irq_mask &= ~(1UL << (irq - 16));
 128        titan_update_irq_hw(titan_cached_irq_mask);
 129        spin_unlock(&titan_irq_lock);
 130}
 131
 132static unsigned int
 133titan_startup_irq(unsigned int irq)
 134{
 135        titan_enable_irq(irq);
 136        return 0;       /* never anything pending */
 137}
 138
 139static void
 140titan_end_irq(unsigned int irq)
 141{
 142        if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 143                titan_enable_irq(irq);
 144}
 145
 146static void
 147titan_cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
 148{
 149        int cpu;
 150
 151        for (cpu = 0; cpu < 4; cpu++) {
 152                if (cpu_isset(cpu, affinity))
 153                        titan_cpu_irq_affinity[cpu] |= 1UL << irq;
 154                else
 155                        titan_cpu_irq_affinity[cpu] &= ~(1UL << irq);
 156        }
 157
 158}
 159
 160static int
 161titan_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
 162{ 
 163        spin_lock(&titan_irq_lock);
 164        titan_cpu_set_irq_affinity(irq - 16, *affinity);
 165        titan_update_irq_hw(titan_cached_irq_mask);
 166        spin_unlock(&titan_irq_lock);
 167
 168        return 0;
 169}
 170
 171static void
 172titan_device_interrupt(unsigned long vector)
 173{
 174        printk("titan_device_interrupt: NOT IMPLEMENTED YET!! \n");
 175}
 176
 177static void 
 178titan_srm_device_interrupt(unsigned long vector)
 179{
 180        int irq;
 181
 182        irq = (vector - 0x800) >> 4;
 183        handle_irq(irq);
 184}
 185
 186
 187static void __init
 188init_titan_irqs(struct irq_chip * ops, int imin, int imax)
 189{
 190        long i;
 191        for (i = imin; i <= imax; ++i) {
 192                irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
 193                irq_desc[i].chip = ops;
 194        }
 195}
 196
 197static struct irq_chip titan_irq_type = {
 198       .name           = "TITAN",
 199       .startup        = titan_startup_irq,
 200       .shutdown       = titan_disable_irq,
 201       .enable         = titan_enable_irq,
 202       .disable        = titan_disable_irq,
 203       .ack            = titan_disable_irq,
 204       .end            = titan_end_irq,
 205       .set_affinity   = titan_set_irq_affinity,
 206};
 207
 208static irqreturn_t
 209titan_intr_nop(int irq, void *dev_id)
 210{
 211      /*
 212       * This is a NOP interrupt handler for the purposes of
 213       * event counting -- just return.
 214       */                                                                     
 215       return IRQ_HANDLED;
 216}
 217
 218static void __init
 219titan_init_irq(void)
 220{
 221        if (alpha_using_srm && !alpha_mv.device_interrupt)
 222                alpha_mv.device_interrupt = titan_srm_device_interrupt;
 223        if (!alpha_mv.device_interrupt)
 224                alpha_mv.device_interrupt = titan_device_interrupt;
 225
 226        titan_update_irq_hw(0);
 227
 228        init_titan_irqs(&titan_irq_type, 16, 63 + 16);
 229}
 230  
 231static void __init
 232titan_legacy_init_irq(void)
 233{
 234        /* init the legacy dma controller */
 235        outb(0, DMA1_RESET_REG);
 236        outb(0, DMA2_RESET_REG);
 237        outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
 238        outb(0, DMA2_MASK_REG);
 239
 240        /* init the legacy irq controller */
 241        init_i8259a_irqs();
 242
 243        /* init the titan irqs */
 244        titan_init_irq();
 245}
 246
 247void
 248titan_dispatch_irqs(u64 mask)
 249{
 250        unsigned long vector;
 251
 252        /*
 253         * Mask down to those interrupts which are enable on this processor
 254         */
 255        mask &= titan_cpu_irq_affinity[smp_processor_id()];
 256
 257        /*
 258         * Dispatch all requested interrupts 
 259         */
 260        while (mask) {
 261                /* convert to SRM vector... priority is <63> -> <0> */
 262                vector = 63 - __kernel_ctlz(mask);
 263                mask &= ~(1UL << vector);       /* clear it out          */
 264                vector = 0x900 + (vector << 4); /* convert to SRM vector */
 265                
 266                /* dispatch it */
 267                alpha_mv.device_interrupt(vector);
 268        }
 269}
 270  
 271
 272/*
 273 * Titan Family
 274 */
 275static void __init
 276titan_request_irq(unsigned int irq, irq_handler_t handler,
 277                  unsigned long irqflags, const char *devname,
 278                  void *dev_id)
 279{
 280        int err;
 281        err = request_irq(irq, handler, irqflags, devname, dev_id);
 282        if (err) {
 283                printk("titan_request_irq for IRQ %d returned %d; ignoring\n",
 284                       irq, err);
 285        }
 286}
 287
 288static void __init
 289titan_late_init(void)
 290{
 291        /*
 292         * Enable the system error interrupts. These interrupts are 
 293         * all reported to the kernel as machine checks, so the handler
 294         * is a nop so it can be called to count the individual events.
 295         */
 296        titan_request_irq(63+16, titan_intr_nop, IRQF_DISABLED,
 297                    "CChip Error", NULL);
 298        titan_request_irq(62+16, titan_intr_nop, IRQF_DISABLED,
 299                    "PChip 0 H_Error", NULL);
 300        titan_request_irq(61+16, titan_intr_nop, IRQF_DISABLED,
 301                    "PChip 1 H_Error", NULL);
 302        titan_request_irq(60+16, titan_intr_nop, IRQF_DISABLED,
 303                    "PChip 0 C_Error", NULL);
 304        titan_request_irq(59+16, titan_intr_nop, IRQF_DISABLED,
 305                    "PChip 1 C_Error", NULL);
 306
 307        /* 
 308         * Register our error handlers.
 309         */
 310        titan_register_error_handlers();
 311
 312        /*
 313         * Check if the console left us any error logs.
 314         */
 315        cdl_check_console_data_log();
 316
 317}
 318
 319static int __devinit
 320titan_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 321{
 322        u8 intline;
 323        int irq;
 324
 325        /* Get the current intline.  */
 326        pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline);
 327        irq = intline;
 328
 329        /* Is it explicitly routed through ISA?  */
 330        if ((irq & 0xF0) == 0xE0)
 331                return irq;
 332 
 333        /* Offset by 16 to make room for ISA interrupts 0 - 15.  */
 334        return irq + 16;
 335}
 336
 337static void __init
 338titan_init_pci(void)
 339{
 340        /*
 341         * This isn't really the right place, but there's some init
 342         * that needs to be done after everything is basically up.
 343         */
 344        titan_late_init();
 345 
 346        pci_probe_only = 1;
 347        common_init_pci();
 348        SMC669_Init(0);
 349        locate_and_init_vga(NULL);
 350}
 351
 352
 353/*
 354 * Privateer
 355 */
 356static void __init
 357privateer_init_pci(void)
 358{
 359        /*
 360         * Hook a couple of extra err interrupts that the
 361         * common titan code won't.
 362         */
 363        titan_request_irq(53+16, titan_intr_nop, IRQF_DISABLED,
 364                    "NMI", NULL);
 365        titan_request_irq(50+16, titan_intr_nop, IRQF_DISABLED,
 366                    "Temperature Warning", NULL);
 367
 368        /*
 369         * Finish with the common version.
 370         */
 371        return titan_init_pci();
 372}
 373
 374
 375/*
 376 * The System Vectors.
 377 */
 378struct alpha_machine_vector titan_mv __initmv = {
 379        .vector_name            = "TITAN",
 380        DO_EV6_MMU,
 381        DO_DEFAULT_RTC,
 382        DO_TITAN_IO,
 383        .machine_check          = titan_machine_check,
 384        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
 385        .min_io_address         = DEFAULT_IO_BASE,
 386        .min_mem_address        = DEFAULT_MEM_BASE,
 387        .pci_dac_offset         = TITAN_DAC_OFFSET,
 388
 389        .nr_irqs                = 80,   /* 64 + 16 */
 390        /* device_interrupt will be filled in by titan_init_irq */
 391
 392        .agp_info               = titan_agp_info,
 393
 394        .init_arch              = titan_init_arch,
 395        .init_irq               = titan_legacy_init_irq,
 396        .init_rtc               = common_init_rtc,
 397        .init_pci               = titan_init_pci,
 398
 399        .kill_arch              = titan_kill_arch,
 400        .pci_map_irq            = titan_map_irq,
 401        .pci_swizzle            = common_swizzle,
 402};
 403ALIAS_MV(titan)
 404
 405struct alpha_machine_vector privateer_mv __initmv = {
 406        .vector_name            = "PRIVATEER",
 407        DO_EV6_MMU,
 408        DO_DEFAULT_RTC,
 409        DO_TITAN_IO,
 410        .machine_check          = privateer_machine_check,
 411        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
 412        .min_io_address         = DEFAULT_IO_BASE,
 413        .min_mem_address        = DEFAULT_MEM_BASE,
 414        .pci_dac_offset         = TITAN_DAC_OFFSET,
 415
 416        .nr_irqs                = 80,   /* 64 + 16 */
 417        /* device_interrupt will be filled in by titan_init_irq */
 418
 419        .agp_info               = titan_agp_info,
 420
 421        .init_arch              = titan_init_arch,
 422        .init_irq               = titan_legacy_init_irq,
 423        .init_rtc               = common_init_rtc,
 424        .init_pci               = privateer_init_pci,
 425
 426        .kill_arch              = titan_kill_arch,
 427        .pci_map_irq            = titan_map_irq,
 428        .pci_swizzle            = common_swizzle,
 429};
 430/* No alpha_mv alias for privateer since we compile it 
 431   in unconditionally with titan; setup_arch knows how to cope. */
 432