linux/arch/alpha/kernel/sys_takara.c
<<
>>
Prefs
   1/*
   2 *      linux/arch/alpha/kernel/sys_takara.c
   3 *
   4 *      Copyright (C) 1995 David A Rusling
   5 *      Copyright (C) 1996 Jay A Estabrook
   6 *      Copyright (C) 1998, 1999 Richard Henderson
   7 *
   8 * Code supporting the TAKARA.
   9 */
  10
  11#include <linux/kernel.h>
  12#include <linux/types.h>
  13#include <linux/mm.h>
  14#include <linux/sched.h>
  15#include <linux/pci.h>
  16#include <linux/init.h>
  17
  18#include <asm/ptrace.h>
  19#include <asm/dma.h>
  20#include <asm/irq.h>
  21#include <asm/mmu_context.h>
  22#include <asm/io.h>
  23#include <asm/pgtable.h>
  24#include <asm/core_cia.h>
  25#include <asm/tlbflush.h>
  26
  27#include "proto.h"
  28#include "irq_impl.h"
  29#include "pci_impl.h"
  30#include "machvec_impl.h"
  31#include "pc873xx.h"
  32
  33/* Note mask bit is true for DISABLED irqs.  */
  34static unsigned long cached_irq_mask[2] = { -1, -1 };
  35
  36static inline void
  37takara_update_irq_hw(unsigned long irq, unsigned long mask)
  38{
  39        int regaddr;
  40
  41        mask = (irq >= 64 ? mask << 16 : mask >> ((irq - 16) & 0x30));
  42        regaddr = 0x510 + (((irq - 16) >> 2) & 0x0c);
  43        outl(mask & 0xffff0000UL, regaddr);
  44}
  45
  46static inline void
  47takara_enable_irq(struct irq_data *d)
  48{
  49        unsigned int irq = d->irq;
  50        unsigned long mask;
  51        mask = (cached_irq_mask[irq >= 64] &= ~(1UL << (irq & 63)));
  52        takara_update_irq_hw(irq, mask);
  53}
  54
  55static void
  56takara_disable_irq(struct irq_data *d)
  57{
  58        unsigned int irq = d->irq;
  59        unsigned long mask;
  60        mask = (cached_irq_mask[irq >= 64] |= 1UL << (irq & 63));
  61        takara_update_irq_hw(irq, mask);
  62}
  63
  64static struct irq_chip takara_irq_type = {
  65        .name           = "TAKARA",
  66        .irq_unmask     = takara_enable_irq,
  67        .irq_mask       = takara_disable_irq,
  68        .irq_mask_ack   = takara_disable_irq,
  69};
  70
  71static void
  72takara_device_interrupt(unsigned long vector)
  73{
  74        unsigned intstatus;
  75
  76        /*
  77         * The PALcode will have passed us vectors 0x800 or 0x810,
  78         * which are fairly arbitrary values and serve only to tell
  79         * us whether an interrupt has come in on IRQ0 or IRQ1. If
  80         * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's
  81         * probably ISA, but PCI interrupts can come through IRQ0
  82         * as well if the interrupt controller isn't in accelerated
  83         * mode.
  84         *
  85         * OTOH, the accelerator thing doesn't seem to be working
  86         * overly well, so what we'll do instead is try directly
  87         * examining the Master Interrupt Register to see if it's a
  88         * PCI interrupt, and if _not_ then we'll pass it on to the
  89         * ISA handler.
  90         */
  91
  92        intstatus = inw(0x500) & 15;
  93        if (intstatus) {
  94                /*
  95                 * This is a PCI interrupt. Check each bit and
  96                 * despatch an interrupt if it's set.
  97                 */
  98
  99                if (intstatus & 8) handle_irq(16+3);
 100                if (intstatus & 4) handle_irq(16+2);
 101                if (intstatus & 2) handle_irq(16+1);
 102                if (intstatus & 1) handle_irq(16+0);
 103        } else {
 104                isa_device_interrupt (vector);
 105        }
 106}
 107
 108static void 
 109takara_srm_device_interrupt(unsigned long vector)
 110{
 111        int irq = (vector - 0x800) >> 4;
 112        handle_irq(irq);
 113}
 114
 115static void __init
 116takara_init_irq(void)
 117{
 118        long i;
 119
 120        init_i8259a_irqs();
 121
 122        if (alpha_using_srm) {
 123                alpha_mv.device_interrupt = takara_srm_device_interrupt;
 124        } else {
 125                unsigned int ctlreg = inl(0x500);
 126
 127                /* Return to non-accelerated mode.  */
 128                ctlreg &= ~0x8000;
 129                outl(ctlreg, 0x500);
 130
 131                /* Enable the PCI interrupt register.  */
 132                ctlreg = 0x05107c00;
 133                outl(ctlreg, 0x500);
 134        }
 135
 136        for (i = 16; i < 128; i += 16)
 137                takara_update_irq_hw(i, -1);
 138
 139        for (i = 16; i < 128; ++i) {
 140                irq_set_chip_and_handler(i, &takara_irq_type,
 141                                         handle_level_irq);
 142                irq_set_status_flags(i, IRQ_LEVEL);
 143        }
 144
 145        common_init_isa_dma();
 146}
 147
 148
 149/*
 150 * The Takara has PCI devices 1, 2, and 3 configured to slots 20,
 151 * 19, and 18 respectively, in the default configuration. They can
 152 * also be jumpered to slots 8, 7, and 6 respectively, which is fun
 153 * because the SIO ISA bridge can also be slot 7. However, the SIO
 154 * doesn't explicitly generate PCI-type interrupts, so we can
 155 * assign it whatever the hell IRQ we like and it doesn't matter.
 156 */
 157
 158static int __init
 159takara_map_irq_srm(const struct pci_dev *dev, u8 slot, u8 pin)
 160{
 161        static char irq_tab[15][5] __initdata = {
 162                { 16+3, 16+3, 16+3, 16+3, 16+3},   /* slot  6 == device 3 */
 163                { 16+2, 16+2, 16+2, 16+2, 16+2},   /* slot  7 == device 2 */
 164                { 16+1, 16+1, 16+1, 16+1, 16+1},   /* slot  8 == device 1 */
 165                {   -1,   -1,   -1,   -1,   -1},   /* slot  9 == nothing */
 166                {   -1,   -1,   -1,   -1,   -1},   /* slot 10 == nothing */
 167                {   -1,   -1,   -1,   -1,   -1},   /* slot 11 == nothing */
 168                /* These are behind the bridges.  */
 169                {   12,   12,   13,   14,   15},   /* slot 12 == nothing */
 170                {    8,    8,    9,   19,   11},   /* slot 13 == nothing */
 171                {    4,    4,    5,    6,    7},   /* slot 14 == nothing */
 172                {    0,    0,    1,    2,    3},   /* slot 15 == nothing */
 173                {   -1,   -1,   -1,   -1,   -1},   /* slot 16 == nothing */
 174                {64+ 0, 64+0, 64+1, 64+2, 64+3},   /* slot 17= device 4 */
 175                {48+ 0, 48+0, 48+1, 48+2, 48+3},   /* slot 18= device 3 */
 176                {32+ 0, 32+0, 32+1, 32+2, 32+3},   /* slot 19= device 2 */
 177                {16+ 0, 16+0, 16+1, 16+2, 16+3},   /* slot 20= device 1 */
 178        };
 179        const long min_idsel = 6, max_idsel = 20, irqs_per_slot = 5;
 180        int irq = COMMON_TABLE_LOOKUP;
 181        if (irq >= 0 && irq < 16) {
 182                /* Guess that we are behind a bridge.  */
 183                unsigned int busslot = PCI_SLOT(dev->bus->self->devfn);
 184                irq += irq_tab[busslot-min_idsel][0];
 185        }
 186        return irq;
 187}
 188
 189static int __init
 190takara_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 191{
 192        static char irq_tab[15][5] __initdata = {
 193                { 16+3, 16+3, 16+3, 16+3, 16+3},   /* slot  6 == device 3 */
 194                { 16+2, 16+2, 16+2, 16+2, 16+2},   /* slot  7 == device 2 */
 195                { 16+1, 16+1, 16+1, 16+1, 16+1},   /* slot  8 == device 1 */
 196                {   -1,   -1,   -1,   -1,   -1},   /* slot  9 == nothing */
 197                {   -1,   -1,   -1,   -1,   -1},   /* slot 10 == nothing */
 198                {   -1,   -1,   -1,   -1,   -1},   /* slot 11 == nothing */
 199                {   -1,   -1,   -1,   -1,   -1},   /* slot 12 == nothing */
 200                {   -1,   -1,   -1,   -1,   -1},   /* slot 13 == nothing */
 201                {   -1,   -1,   -1,   -1,   -1},   /* slot 14 == nothing */
 202                {   -1,   -1,   -1,   -1,   -1},   /* slot 15 == nothing */
 203                {   -1,   -1,   -1,   -1,   -1},   /* slot 16 == nothing */
 204                {   -1,   -1,   -1,   -1,   -1},   /* slot 17 == nothing */
 205                { 16+3, 16+3, 16+3, 16+3, 16+3},   /* slot 18 == device 3 */
 206                { 16+2, 16+2, 16+2, 16+2, 16+2},   /* slot 19 == device 2 */
 207                { 16+1, 16+1, 16+1, 16+1, 16+1},   /* slot 20 == device 1 */
 208        };
 209        const long min_idsel = 6, max_idsel = 20, irqs_per_slot = 5;
 210        return COMMON_TABLE_LOOKUP;
 211}
 212
 213static u8 __init
 214takara_swizzle(struct pci_dev *dev, u8 *pinp)
 215{
 216        int slot = PCI_SLOT(dev->devfn);
 217        int pin = *pinp;
 218        unsigned int ctlreg = inl(0x500);
 219        unsigned int busslot;
 220
 221        if (!dev->bus->self)
 222                return slot;
 223
 224        busslot = PCI_SLOT(dev->bus->self->devfn);
 225        /* Check for built-in bridges.  */
 226        if (dev->bus->number != 0
 227            && busslot > 16
 228            && ((1<<(36-busslot)) & ctlreg)) {
 229                if (pin == 1)
 230                        pin += (20 - busslot);
 231                else {
 232                        printk(KERN_WARNING "takara_swizzle: can only "
 233                               "handle cards with INTA IRQ pin.\n");
 234                }
 235        } else {
 236                /* Must be a card-based bridge.  */
 237                printk(KERN_WARNING "takara_swizzle: cannot handle "
 238                       "card-bridge behind builtin bridge yet.\n");
 239        }
 240
 241        *pinp = pin;
 242        return slot;
 243}
 244
 245static void __init
 246takara_init_pci(void)
 247{
 248        if (alpha_using_srm)
 249                alpha_mv.pci_map_irq = takara_map_irq_srm;
 250
 251        cia_init_pci();
 252
 253        if (pc873xx_probe() == -1) {
 254                printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n");
 255        } else {
 256                printk(KERN_INFO "Found %s Super IO chip at 0x%x\n",
 257                        pc873xx_get_model(), pc873xx_get_base());
 258                pc873xx_enable_ide();
 259        }
 260}
 261
 262
 263/*
 264 * The System Vector
 265 */
 266
 267struct alpha_machine_vector takara_mv __initmv = {
 268        .vector_name            = "Takara",
 269        DO_EV5_MMU,
 270        DO_DEFAULT_RTC,
 271        DO_CIA_IO,
 272        .machine_check          = cia_machine_check,
 273        .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
 274        .min_io_address         = DEFAULT_IO_BASE,
 275        .min_mem_address        = CIA_DEFAULT_MEM_BASE,
 276
 277        .nr_irqs                = 128,
 278        .device_interrupt       = takara_device_interrupt,
 279
 280        .init_arch              = cia_init_arch,
 281        .init_irq               = takara_init_irq,
 282        .init_rtc               = common_init_rtc,
 283        .init_pci               = takara_init_pci,
 284        .kill_arch              = cia_kill_arch,
 285        .pci_map_irq            = takara_map_irq,
 286        .pci_swizzle            = takara_swizzle,
 287};
 288ALIAS_MV(takara)
 289