2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved.
9 #include <linux/types.h>
10 #include <asm/sn/sgi.h>
11 #include <asm/sn/pci/pciio.h>
12 #include <asm/sn/pci/pcibr.h>
13 #include <asm/sn/pci/pcibr_private.h>
14 #include <asm/sn/pci/pci_defs.h>
16 extern pcibr_info_t pcibr_info_get(vertex_hdl_t);
18 uint64_t pcibr_config_get(vertex_hdl_t, unsigned, unsigned);
19 uint64_t do_pcibr_config_get(cfg_p, unsigned, unsigned);
20 void pcibr_config_set(vertex_hdl_t, unsigned, unsigned, uint64_t);
21 void do_pcibr_config_set(cfg_p, unsigned, unsigned, uint64_t);
24 * fancy snia bit twiddling....
26 #define CBP(b,r) (((volatile uint8_t *) b)[(r)])
27 #define CSP(b,r) (((volatile uint16_t *) b)[((r)/2)])
28 #define CWP(b,r) (((volatile uint32_t *) b)[(r)/4])
31 * Return a config space address for given slot / func / offset. Note the
32 * returned pointer is a 32bit word (ie. cfg_p) aligned pointer pointing to
33 * the 32bit word that contains the "offset" byte.
36 pcibr_func_config_addr(pcibr_soft_t soft, pciio_bus_t bus, pciio_slot_t slot,
37 pciio_function_t func, int offset)
43 pcireg_type1_cntr_set(soft, ((bus << 16) | (slot << 11)));
44 return (pcireg_type1_cfg_addr(soft, func, offset));
50 return (pcireg_type0_cfg_addr(soft, slot, func, offset));
54 * Return config space address for given slot / offset. Note the returned
55 * pointer is a 32bit word (ie. cfg_p) aligned pointer pointing to the
56 * 32bit word that contains the "offset" byte.
59 pcibr_slot_config_addr(pcibr_soft_t soft, pciio_slot_t slot, int offset)
61 return pcibr_func_config_addr(soft, 0, slot, 0, offset);
65 * Set config space data for given slot / func / offset
68 pcibr_func_config_set(pcibr_soft_t soft, pciio_slot_t slot,
69 pciio_function_t func, int offset, unsigned val)
73 cfg_base = pcibr_func_config_addr(soft, 0, slot, func, 0);
74 do_pcibr_config_set(cfg_base, offset, sizeof(unsigned), val);
77 int pcibr_config_debug = 0;
80 pcibr_config_addr(vertex_hdl_t conn,
83 pcibr_info_t pcibr_info;
84 pciio_bus_t pciio_bus;
85 pciio_slot_t pciio_slot;
86 pciio_function_t pciio_func;
87 cfg_p cfgbase = (cfg_p)0;
88 pciio_info_t pciio_info;
90 pciio_info = pciio_info_get(conn);
91 pcibr_info = pcibr_info_get(conn);
94 * Determine the PCI bus/slot/func to generate a config address for.
97 if (pciio_info_type1_get(pciio_info)) {
99 * Conn is a vhdl which uses TYPE 1 addressing explicitly passed
102 pciio_bus = PCI_TYPE1_BUS(reg);
103 pciio_slot = PCI_TYPE1_SLOT(reg);
104 pciio_func = PCI_TYPE1_FUNC(reg);
106 ASSERT(pciio_bus != 0);
109 * Conn is directly connected to the host bus. PCI bus number is
110 * hardcoded to 0 (even though it may have a logical bus number != 0)
111 * and slot/function are derived from the pcibr_info_t associated
116 pciio_slot = PCIBR_INFO_SLOT_GET_INT(pcibr_info);
117 if (pciio_slot == PCIIO_SLOT_NONE)
118 pciio_slot = PCI_TYPE1_SLOT(reg);
120 pciio_func = pcibr_info->f_func;
121 if (pciio_func == PCIIO_FUNC_NONE)
122 pciio_func = PCI_TYPE1_FUNC(reg);
125 cfgbase = pcibr_func_config_addr((pcibr_soft_t) pcibr_info->f_mfast,
126 pciio_bus, pciio_slot, pciio_func, 0);
132 pcibr_config_get(vertex_hdl_t conn,
136 return do_pcibr_config_get(pcibr_config_addr(conn, reg),
137 PCI_TYPE1_REG(reg), size);
141 do_pcibr_config_get(cfg_p cfgbase,
147 value = CWP(cfgbase, reg);
149 value >>= 8 * (reg & 3);
151 value &= (1 << (8 * size)) - 1;
156 pcibr_config_set(vertex_hdl_t conn,
161 do_pcibr_config_set(pcibr_config_addr(conn, reg),
162 PCI_TYPE1_REG(reg), size, value);
166 do_pcibr_config_set(cfg_p cfgbase,
173 CBP(cfgbase, reg) = value;
177 CBP(cfgbase, reg) = value;
178 CBP(cfgbase, reg + 1) = value >> 8;
180 CSP(cfgbase, reg) = value;
184 CBP(cfgbase, reg) = value;
185 CSP(cfgbase, (reg + 1)) = value >> 8;
187 CSP(cfgbase, reg) = value;
188 CBP(cfgbase, reg + 2) = value >> 16;
192 CWP(cfgbase, reg) = value;