linux/arch/alpha/kernel/core_polaris.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *      linux/arch/alpha/kernel/core_polaris.c
   4 *
   5 * POLARIS chip-specific code
   6 */
   7
   8#define __EXTERN_INLINE inline
   9#include <asm/io.h>
  10#include <asm/core_polaris.h>
  11#undef __EXTERN_INLINE
  12
  13#include <linux/types.h>
  14#include <linux/pci.h>
  15#include <linux/sched.h>
  16#include <linux/init.h>
  17
  18#include <asm/ptrace.h>
  19
  20#include "proto.h"
  21#include "pci_impl.h"
  22
  23/*
  24 * BIOS32-style PCI interface:
  25 */
  26
  27#define DEBUG_CONFIG 0
  28
  29#if DEBUG_CONFIG
  30# define DBG_CFG(args)  printk args
  31#else
  32# define DBG_CFG(args)
  33#endif
  34
  35
  36/*
  37 * Given a bus, device, and function number, compute resulting
  38 * configuration space address.  This is fairly straightforward
  39 * on POLARIS, since the chip itself generates Type 0 or Type 1
  40 * cycles automatically depending on the bus number (Bus 0 is
  41 * hardwired to Type 0, all others are Type 1.  Peer bridges
  42 * are not supported).
  43 *
  44 * All types:
  45 *
  46 *  3 3 3 3|3 3 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
  47 *  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 9 8|7 6 5 4|3 2 1 0
  48 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  49 * |1|1|1|1|1|0|0|1|1|1|1|1|1|1|1|0|B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|x|x|
  50 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  51 *
  52 *      23:16   bus number (8 bits = 128 possible buses)
  53 *      15:11   Device number (5 bits)
  54 *      10:8    function number
  55 *       7:2    register number
  56 *  
  57 * Notes:
  58 *      The function number selects which function of a multi-function device 
  59 *      (e.g., scsi and ethernet).
  60 * 
  61 *      The register selects a DWORD (32 bit) register offset.  Hence it
  62 *      doesn't get shifted by 2 bits as we want to "drop" the bottom two
  63 *      bits.
  64 */
  65
  66static int
  67mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
  68             unsigned long *pci_addr, u8 *type1)
  69{
  70        u8 bus = pbus->number;
  71
  72        *type1 = (bus == 0) ? 0 : 1;
  73        *pci_addr = (bus << 16) | (device_fn << 8) | (where) |
  74                    POLARIS_DENSE_CONFIG_BASE;
  75
  76        DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
  77                 " returning address 0x%p\n"
  78                 bus, device_fn, where, *pci_addr));
  79
  80        return 0;
  81}
  82
  83static int
  84polaris_read_config(struct pci_bus *bus, unsigned int devfn, int where,
  85                    int size, u32 *value)
  86{
  87        unsigned long addr;
  88        unsigned char type1;
  89
  90        if (mk_conf_addr(bus, devfn, where, &addr, &type1))
  91                return PCIBIOS_DEVICE_NOT_FOUND;
  92
  93        switch (size) {
  94        case 1:
  95                *value = __kernel_ldbu(*(vucp)addr);
  96                break;
  97        case 2:
  98                *value = __kernel_ldwu(*(vusp)addr);
  99                break;
 100        case 4:
 101                *value = *(vuip)addr;
 102                break;
 103        }
 104
 105        return PCIBIOS_SUCCESSFUL;
 106}
 107
 108
 109static int 
 110polaris_write_config(struct pci_bus *bus, unsigned int devfn, int where,
 111                     int size, u32 value)
 112{
 113        unsigned long addr;
 114        unsigned char type1;
 115
 116        if (mk_conf_addr(bus, devfn, where, &addr, &type1))
 117                return PCIBIOS_DEVICE_NOT_FOUND;
 118
 119        switch (size) {
 120        case 1:
 121                __kernel_stb(value, *(vucp)addr);
 122                mb();
 123                __kernel_ldbu(*(vucp)addr);
 124                break;
 125        case 2:
 126                __kernel_stw(value, *(vusp)addr);
 127                mb();
 128                __kernel_ldwu(*(vusp)addr);
 129                break;
 130        case 4:
 131                *(vuip)addr = value;
 132                mb();
 133                *(vuip)addr;
 134                break;
 135        }
 136
 137        return PCIBIOS_SUCCESSFUL;
 138}
 139
 140struct pci_ops polaris_pci_ops = 
 141{
 142        .read =         polaris_read_config,
 143        .write =        polaris_write_config,
 144};
 145
 146void __init
 147polaris_init_arch(void)
 148{
 149        struct pci_controller *hose;
 150
 151        /* May need to initialize error reporting (see PCICTL0/1), but
 152         * for now assume that the firmware has done the right thing
 153         * already.
 154         */
 155#if 0
 156        printk("polaris_init_arch(): trusting firmware for setup\n");
 157#endif
 158
 159        /*
 160         * Create our single hose.
 161         */
 162
 163        pci_isa_hose = hose = alloc_pci_controller();
 164        hose->io_space = &ioport_resource;
 165        hose->mem_space = &iomem_resource;
 166        hose->index = 0;
 167
 168        hose->sparse_mem_base = 0;
 169        hose->dense_mem_base = POLARIS_DENSE_MEM_BASE - IDENT_ADDR;
 170        hose->sparse_io_base = 0;
 171        hose->dense_io_base = POLARIS_DENSE_IO_BASE - IDENT_ADDR;
 172
 173        hose->sg_isa = hose->sg_pci = NULL;
 174
 175        /* The I/O window is fixed at 2G @ 2G.  */
 176        __direct_map_base = 0x80000000;
 177        __direct_map_size = 0x80000000;
 178}
 179
 180static inline void
 181polaris_pci_clr_err(void)
 182{
 183        *(vusp)POLARIS_W_STATUS;
 184        /* Write 1's to settable bits to clear errors */
 185        *(vusp)POLARIS_W_STATUS = 0x7800;
 186        mb();
 187        *(vusp)POLARIS_W_STATUS;
 188}
 189
 190void
 191polaris_machine_check(unsigned long vector, unsigned long la_ptr)
 192{
 193        /* Clear the error before any reporting.  */
 194        mb();
 195        mb();
 196        draina();
 197        polaris_pci_clr_err();
 198        wrmces(0x7);
 199        mb();
 200
 201        process_mcheck_info(vector, la_ptr, "POLARIS",
 202                            mcheck_expected(0));
 203}
 204