linux/arch/alpha/kernel/core_apecs.c
<<
>>
Prefs
   1/*
   2 *      linux/arch/alpha/kernel/core_apecs.c
   3 *
   4 * Rewritten for Apecs from the lca.c from:
   5 *
   6 * Written by David Mosberger (davidm@cs.arizona.edu) with some code
   7 * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
   8 * bios code.
   9 *
  10 * Code common to all APECS core logic chips.
  11 */
  12
  13#define __EXTERN_INLINE inline
  14#include <asm/io.h>
  15#include <asm/core_apecs.h>
  16#undef __EXTERN_INLINE
  17
  18#include <linux/types.h>
  19#include <linux/pci.h>
  20#include <linux/init.h>
  21
  22#include <asm/ptrace.h>
  23#include <asm/smp.h>
  24#include <asm/mce.h>
  25
  26#include "proto.h"
  27#include "pci_impl.h"
  28
  29/*
  30 * NOTE: Herein lie back-to-back mb instructions.  They are magic. 
  31 * One plausible explanation is that the i/o controller does not properly
  32 * handle the system transaction.  Another involves timing.  Ho hum.
  33 */
  34
  35/*
  36 * BIOS32-style PCI interface:
  37 */
  38
  39#define DEBUG_CONFIG 0
  40
  41#if DEBUG_CONFIG
  42# define DBGC(args)     printk args
  43#else
  44# define DBGC(args)
  45#endif
  46
  47#define vuip    volatile unsigned int  *
  48
  49/*
  50 * Given a bus, device, and function number, compute resulting
  51 * configuration space address and setup the APECS_HAXR2 register
  52 * accordingly.  It is therefore not safe to have concurrent
  53 * invocations to configuration space access routines, but there
  54 * really shouldn't be any need for this.
  55 *
  56 * Type 0:
  57 *
  58 *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
  59 *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
  60 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  61 * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0|
  62 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  63 *
  64 *      31:11   Device select bit.
  65 *      10:8    Function number
  66 *       7:2    Register number
  67 *
  68 * Type 1:
  69 *
  70 *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
  71 *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
  72 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  73 * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
  74 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  75 *
  76 *      31:24   reserved
  77 *      23:16   bus number (8 bits = 128 possible buses)
  78 *      15:11   Device number (5 bits)
  79 *      10:8    function number
  80 *       7:2    register number
  81 *  
  82 * Notes:
  83 *      The function number selects which function of a multi-function device 
  84 *      (e.g., SCSI and Ethernet).
  85 * 
  86 *      The register selects a DWORD (32 bit) register offset.  Hence it
  87 *      doesn't get shifted by 2 bits as we want to "drop" the bottom two
  88 *      bits.
  89 */
  90
  91static int
  92mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
  93             unsigned long *pci_addr, unsigned char *type1)
  94{
  95        unsigned long addr;
  96        u8 bus = pbus->number;
  97
  98        DBGC(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
  99              " pci_addr=0x%p, type1=0x%p)\n",
 100              bus, device_fn, where, pci_addr, type1));
 101
 102        if (bus == 0) {
 103                int device = device_fn >> 3;
 104
 105                /* type 0 configuration cycle: */
 106
 107                if (device > 20) {
 108                        DBGC(("mk_conf_addr: device (%d) > 20, returning -1\n",
 109                              device));
 110                        return -1;
 111                }
 112
 113                *type1 = 0;
 114                addr = (device_fn << 8) | (where);
 115        } else {
 116                /* type 1 configuration cycle: */
 117                *type1 = 1;
 118                addr = (bus << 16) | (device_fn << 8) | (where);
 119        }
 120        *pci_addr = addr;
 121        DBGC(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
 122        return 0;
 123}
 124
 125static unsigned int
 126conf_read(unsigned long addr, unsigned char type1)
 127{
 128        unsigned long flags;
 129        unsigned int stat0, value;
 130        unsigned int haxr2 = 0;
 131
 132        local_irq_save(flags);  /* avoid getting hit by machine check */
 133
 134        DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
 135
 136        /* Reset status register to avoid losing errors.  */
 137        stat0 = *(vuip)APECS_IOC_DCSR;
 138        *(vuip)APECS_IOC_DCSR = stat0;
 139        mb();
 140        DBGC(("conf_read: APECS DCSR was 0x%x\n", stat0));
 141
 142        /* If Type1 access, must set HAE #2. */
 143        if (type1) {
 144                haxr2 = *(vuip)APECS_IOC_HAXR2;
 145                mb();
 146                *(vuip)APECS_IOC_HAXR2 = haxr2 | 1;
 147                DBGC(("conf_read: TYPE1 access\n"));
 148        }
 149
 150        draina();
 151        mcheck_expected(0) = 1;
 152        mcheck_taken(0) = 0;
 153        mb();
 154
 155        /* Access configuration space.  */
 156
 157        /* Some SRMs step on these registers during a machine check.  */
 158        asm volatile("ldl %0,%1; mb; mb" : "=r"(value) : "m"(*(vuip)addr)
 159                     : "$9", "$10", "$11", "$12", "$13", "$14", "memory");
 160
 161        if (mcheck_taken(0)) {
 162                mcheck_taken(0) = 0;
 163                value = 0xffffffffU;
 164                mb();
 165        }
 166        mcheck_expected(0) = 0;
 167        mb();
 168
 169#if 1
 170        /*
 171         * david.rusling@reo.mts.dec.com.  This code is needed for the
 172         * EB64+ as it does not generate a machine check (why I don't
 173         * know).  When we build kernels for one particular platform
 174         * then we can make this conditional on the type.
 175         */
 176        draina();
 177
 178        /* Now look for any errors.  */
 179        stat0 = *(vuip)APECS_IOC_DCSR;
 180        DBGC(("conf_read: APECS DCSR after read 0x%x\n", stat0));
 181
 182        /* Is any error bit set? */
 183        if (stat0 & 0xffe0U) {
 184                /* If not NDEV, print status.  */
 185                if (!(stat0 & 0x0800)) {
 186                        printk("apecs.c:conf_read: got stat0=%x\n", stat0);
 187                }
 188
 189                /* Reset error status.  */
 190                *(vuip)APECS_IOC_DCSR = stat0;
 191                mb();
 192                wrmces(0x7);                    /* reset machine check */
 193                value = 0xffffffff;
 194        }
 195#endif
 196
 197        /* If Type1 access, must reset HAE #2 so normal IO space ops work.  */
 198        if (type1) {
 199                *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1;
 200                mb();
 201        }
 202        local_irq_restore(flags);
 203
 204        return value;
 205}
 206
 207static void
 208conf_write(unsigned long addr, unsigned int value, unsigned char type1)
 209{
 210        unsigned long flags;
 211        unsigned int stat0;
 212        unsigned int haxr2 = 0;
 213
 214        local_irq_save(flags);  /* avoid getting hit by machine check */
 215
 216        /* Reset status register to avoid losing errors.  */
 217        stat0 = *(vuip)APECS_IOC_DCSR;
 218        *(vuip)APECS_IOC_DCSR = stat0;
 219        mb();
 220
 221        /* If Type1 access, must set HAE #2. */
 222        if (type1) {
 223                haxr2 = *(vuip)APECS_IOC_HAXR2;
 224                mb();
 225                *(vuip)APECS_IOC_HAXR2 = haxr2 | 1;
 226        }
 227
 228        draina();
 229        mcheck_expected(0) = 1;
 230        mb();
 231
 232        /* Access configuration space.  */
 233        *(vuip)addr = value;
 234        mb();
 235        mb();  /* magic */
 236        mcheck_expected(0) = 0;
 237        mb();
 238
 239#if 1
 240        /*
 241         * david.rusling@reo.mts.dec.com.  This code is needed for the
 242         * EB64+ as it does not generate a machine check (why I don't
 243         * know).  When we build kernels for one particular platform
 244         * then we can make this conditional on the type.
 245         */
 246        draina();
 247
 248        /* Now look for any errors.  */
 249        stat0 = *(vuip)APECS_IOC_DCSR;
 250
 251        /* Is any error bit set? */
 252        if (stat0 & 0xffe0U) {
 253                /* If not NDEV, print status.  */
 254                if (!(stat0 & 0x0800)) {
 255                        printk("apecs.c:conf_write: got stat0=%x\n", stat0);
 256                }
 257
 258                /* Reset error status.  */
 259                *(vuip)APECS_IOC_DCSR = stat0;
 260                mb();
 261                wrmces(0x7);                    /* reset machine check */
 262        }
 263#endif
 264
 265        /* If Type1 access, must reset HAE #2 so normal IO space ops work.  */
 266        if (type1) {
 267                *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1;
 268                mb();
 269        }
 270        local_irq_restore(flags);
 271}
 272
 273static int
 274apecs_read_config(struct pci_bus *bus, unsigned int devfn, int where,
 275                  int size, u32 *value)
 276{
 277        unsigned long addr, pci_addr;
 278        unsigned char type1;
 279        long mask;
 280        int shift;
 281
 282        if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
 283                return PCIBIOS_DEVICE_NOT_FOUND;
 284
 285        mask = (size - 1) * 8;
 286        shift = (where & 3) * 8;
 287        addr = (pci_addr << 5) + mask + APECS_CONF;
 288        *value = conf_read(addr, type1) >> (shift);
 289        return PCIBIOS_SUCCESSFUL;
 290}
 291
 292static int
 293apecs_write_config(struct pci_bus *bus, unsigned int devfn, int where,
 294                   int size, u32 value)
 295{
 296        unsigned long addr, pci_addr;
 297        unsigned char type1;
 298        long mask;
 299
 300        if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
 301                return PCIBIOS_DEVICE_NOT_FOUND;
 302
 303        mask = (size - 1) * 8;
 304        addr = (pci_addr << 5) + mask + APECS_CONF;
 305        conf_write(addr, value << ((where & 3) * 8), type1);
 306        return PCIBIOS_SUCCESSFUL;
 307}
 308
 309struct pci_ops apecs_pci_ops = 
 310{
 311        .read =         apecs_read_config,
 312        .write =        apecs_write_config,
 313};
 314
 315void
 316apecs_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
 317{
 318        wmb();
 319        *(vip)APECS_IOC_TBIA = 0;
 320        mb();
 321}
 322
 323void __init
 324apecs_init_arch(void)
 325{
 326        struct pci_controller *hose;
 327
 328        /*
 329         * Create our single hose.
 330         */
 331
 332        pci_isa_hose = hose = alloc_pci_controller();
 333        hose->io_space = &ioport_resource;
 334        hose->mem_space = &iomem_resource;
 335        hose->index = 0;
 336
 337        hose->sparse_mem_base = APECS_SPARSE_MEM - IDENT_ADDR;
 338        hose->dense_mem_base = APECS_DENSE_MEM - IDENT_ADDR;
 339        hose->sparse_io_base = APECS_IO - IDENT_ADDR;
 340        hose->dense_io_base = 0;
 341
 342        /*
 343         * Set up the PCI to main memory translation windows.
 344         *
 345         * Window 1 is direct access 1GB at 1GB
 346         * Window 2 is scatter-gather 8MB at 8MB (for isa)
 347         */
 348        hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
 349        hose->sg_pci = NULL;
 350        __direct_map_base = 0x40000000;
 351        __direct_map_size = 0x40000000;
 352
 353        *(vuip)APECS_IOC_PB1R = __direct_map_base | 0x00080000;
 354        *(vuip)APECS_IOC_PM1R = (__direct_map_size - 1) & 0xfff00000U;
 355        *(vuip)APECS_IOC_TB1R = 0;
 356
 357        *(vuip)APECS_IOC_PB2R = hose->sg_isa->dma_base | 0x000c0000;
 358        *(vuip)APECS_IOC_PM2R = (hose->sg_isa->size - 1) & 0xfff00000;
 359        *(vuip)APECS_IOC_TB2R = virt_to_phys(hose->sg_isa->ptes) >> 1;
 360
 361        apecs_pci_tbi(hose, 0, -1);
 362
 363        /*
 364         * Finally, clear the HAXR2 register, which gets used
 365         * for PCI Config Space accesses. That is the way
 366         * we want to use it, and we do not want to depend on
 367         * what ARC or SRM might have left behind...
 368         */
 369        *(vuip)APECS_IOC_HAXR2 = 0;
 370        mb();
 371}
 372
 373void
 374apecs_pci_clr_err(void)
 375{
 376        unsigned int jd;
 377
 378        jd = *(vuip)APECS_IOC_DCSR;
 379        if (jd & 0xffe0L) {
 380                *(vuip)APECS_IOC_SEAR;
 381                *(vuip)APECS_IOC_DCSR = jd | 0xffe1L;
 382                mb();
 383                *(vuip)APECS_IOC_DCSR;
 384        }
 385        *(vuip)APECS_IOC_TBIA = (unsigned int)APECS_IOC_TBIA;
 386        mb();
 387        *(vuip)APECS_IOC_TBIA;
 388}
 389
 390void
 391apecs_machine_check(unsigned long vector, unsigned long la_ptr)
 392{
 393        struct el_common *mchk_header;
 394        struct el_apecs_procdata *mchk_procdata;
 395        struct el_apecs_sysdata_mcheck *mchk_sysdata;
 396
 397        mchk_header = (struct el_common *)la_ptr;
 398
 399        mchk_procdata = (struct el_apecs_procdata *)
 400                (la_ptr + mchk_header->proc_offset
 401                 - sizeof(mchk_procdata->paltemp));
 402
 403        mchk_sysdata = (struct el_apecs_sysdata_mcheck *)
 404                (la_ptr + mchk_header->sys_offset);
 405
 406
 407        /* Clear the error before any reporting.  */
 408        mb();
 409        mb(); /* magic */
 410        draina();
 411        apecs_pci_clr_err();
 412        wrmces(0x7);            /* reset machine check pending flag */
 413        mb();
 414
 415        process_mcheck_info(vector, la_ptr, "APECS",
 416                            (mcheck_expected(0)
 417                             && (mchk_sysdata->epic_dcsr & 0x0c00UL)));
 418}
 419