1/* 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 4 * for more details. 5 * 6 * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved. 7 */ 8 9#include <linux/interrupt.h> 10#include <linux/types.h> 11#include <asm/sn/io.h> 12#include <asm/sn/pcibr_provider.h> 13#include <asm/sn/pcibus_provider_defs.h> 14#include <asm/sn/pcidev.h> 15#include <asm/sn/pic.h> 16#include <asm/sn/tiocp.h> 17 18union br_ptr { 19 struct tiocp tio; 20 struct pic pic; 21}; 22 23/* 24 * Control Register Access -- Read/Write 0000_0020 25 */ 26void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, u64 bits) 27{ 28 union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; 29 30 if (pcibus_info) { 31 switch (pcibus_info->pbi_bridge_type) { 32 case PCIBR_BRIDGETYPE_TIOCP: 33 __sn_clrq_relaxed(&ptr->tio.cp_control, bits); 34 break; 35 case PCIBR_BRIDGETYPE_PIC: 36 __sn_clrq_relaxed(&ptr->pic.p_wid_control, bits); 37 break; 38 default: 39 panic 40 ("pcireg_control_bit_clr: unknown bridgetype bridge 0x%p", 41 ptr); 42 } 43 } 44} 45 46void pcireg_control_bit_set(struct pcibus_info *pcibus_info, u64 bits) 47{ 48 union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; 49 50 if (pcibus_info) { 51 switch (pcibus_info->pbi_bridge_type) { 52 case PCIBR_BRIDGETYPE_TIOCP: 53 __sn_setq_relaxed(&ptr->tio.cp_control, bits); 54 break; 55 case PCIBR_BRIDGETYPE_PIC: 56 __sn_setq_relaxed(&ptr->pic.p_wid_control, bits); 57 break; 58 default: 59 panic 60 ("pcireg_control_bit_set: unknown bridgetype bridge 0x%p", 61 ptr); 62 } 63 } 64} 65 66/* 67 * PCI/PCIX Target Flush Register Access -- Read Only 0000_0050 68 */ 69u64 pcireg_tflush_get(struct pcibus_info *pcibus_info) 70{ 71 union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; 72 u64 ret = 0; 73 74 if (pcibus_info) { 75 switch (pcibus_info->pbi_bridge_type) { 76 case PCIBR_BRIDGETYPE_TIOCP: 77 ret = __sn_readq_relaxed(&ptr->tio.cp_tflush); 78 break; 79 case PCIBR_BRIDGETYPE_PIC: 80 ret = __sn_readq_relaxed(&ptr->pic.p_wid_tflush); 81 break; 82 default: 83 panic 84 ("pcireg_tflush_get: unknown bridgetype bridge 0x%p", 85 ptr); 86 } 87 } 88 89 /* Read of the Target Flush should always return zero */ 90 if (ret != 0) 91 panic("pcireg_tflush_get:Target Flush failed\n"); 92 93 return ret; 94} 95 96/* 97 * Interrupt Status Register Access -- Read Only 0000_0100 98 */ 99u64 pcireg_intr_status_get(struct pcibus_info * pcibus_info) 100{ 101 union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; 102 u64 ret = 0; 103 104 if (pcibus_info) { 105 switch (pcibus_info->pbi_bridge_type) { 106 case PCIBR_BRIDGETYPE_TIOCP: 107 ret = __sn_readq_relaxed(&ptr->tio.cp_int_status); 108 break; 109 case PCIBR_BRIDGETYPE_PIC: 110 ret = __sn_readq_relaxed(&ptr->pic.p_int_status); 111 break; 112 default: 113 panic 114 ("pcireg_intr_status_get: unknown bridgetype bridge 0x%p", 115 ptr); 116 } 117 } 118 return ret; 119} 120 121/* 122 * Interrupt Enable Register Access -- Read/Write 0000_0108 123 */ 124void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, u64 bits) 125{ 126 union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; 127 128 if (pcibus_info) { 129 switch (pcibus_info->pbi_bridge_type) { 130 case PCIBR_BRIDGETYPE_TIOCP: 131 __sn_clrq_relaxed(&ptr->tio.cp_int_enable, bits); 132 break; 133 case PCIBR_BRIDGETYPE_PIC: 134 __sn_clrq_relaxed(&ptr->pic.p_int_enable, bits); 135 break; 136 default: 137 panic 138 ("pcireg_intr_enable_bit_clr: unknown bridgetype bridge 0x%p", 139 ptr); 140 } 141 } 142} 143 144void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, u64 bits) 145{ 146 union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; 147 148 if (pcibus_info) { 149 switch (pcibus_info->pbi_bridge_type) { 150 case PCIBR_BRIDGETYPE_TIOCP: 151 __sn_setq_relaxed(&ptr->tio.cp_int_enable, bits); 152 break; 153 case PCIBR_BRIDGETYPE_PIC: 154 __sn_setq_relaxed(&ptr->pic.p_int_enable, bits); 155 break; 156 default: 157 panic 158 ("pcireg_intr_enable_bit_set: unknown bridgetype bridge 0x%p", 159 ptr); 160 } 161 } 162} 163 164/* 165 * Intr Host Address Register (int_addr) -- Read/Write 0000_0130 - 0000_0168 166 */ 167void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n, 168 u64 addr) 169{ 170 union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; 171 172 if (pcibus_info) { 173 switch (pcibus_info->pbi_bridge_type) { 174 case PCIBR_BRIDGETYPE_TIOCP: 175 __sn_clrq_relaxed(&ptr->tio.cp_int_addr[int_n], 176 TIOCP_HOST_INTR_ADDR); 177 __sn_setq_relaxed(&ptr->tio.cp_int_addr[int_n], 178 (addr & TIOCP_HOST_INTR_ADDR)); 179 break; 180 case PCIBR_BRIDGETYPE_PIC: 181 __sn_clrq_relaxed(&ptr->pic.p_int_addr[int_n], 182 PIC_HOST_INTR_ADDR); 183 __sn_setq_relaxed(&ptr->pic.p_int_addr[int_n], 184 (addr & PIC_HOST_INTR_ADDR)); 185 break; 186 default: 187 panic 188 ("pcireg_intr_addr_addr_get: unknown bridgetype bridge 0x%p", 189 ptr); 190 } 191 } 192} 193 194/* 195 * Force Interrupt Register Access -- Write Only 0000_01C0 - 0000_01F8 196 */ 197void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n) 198{ 199 union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; 200 201 if (pcibus_info) { 202 switch (pcibus_info->pbi_bridge_type) { 203 case PCIBR_BRIDGETYPE_TIOCP: 204 writeq(1, &ptr->tio.cp_force_pin[int_n]); 205 break; 206 case PCIBR_BRIDGETYPE_PIC: 207 writeq(1, &ptr->pic.p_force_pin[int_n]); 208 break; 209 default: 210 panic 211 ("pcireg_force_intr_set: unknown bridgetype bridge 0x%p", 212 ptr); 213 } 214 } 215} 216 217/* 218 * Device(x) Write Buffer Flush Reg Access -- Read Only 0000_0240 - 0000_0258 219 */ 220u64 pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) 221{ 222 union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; 223 u64 ret = 0; 224 225 if (pcibus_info) { 226 switch (pcibus_info->pbi_bridge_type) { 227 case PCIBR_BRIDGETYPE_TIOCP: 228 ret = 229 __sn_readq_relaxed(&ptr->tio.cp_wr_req_buf[device]); 230 break; 231 case PCIBR_BRIDGETYPE_PIC: 232 ret = 233 __sn_readq_relaxed(&ptr->pic.p_wr_req_buf[device]); 234 break; 235 default: 236 panic("pcireg_wrb_flush_get: unknown bridgetype bridge 0x%p", ptr); 237 } 238 239 } 240 /* Read of the Write Buffer Flush should always return zero */ 241 return ret; 242} 243 244void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index, 245 u64 val) 246{ 247 union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; 248 249 if (pcibus_info) { 250 switch (pcibus_info->pbi_bridge_type) { 251 case PCIBR_BRIDGETYPE_TIOCP: 252 writeq(val, &ptr->tio.cp_int_ate_ram[ate_index]); 253 break; 254 case PCIBR_BRIDGETYPE_PIC: 255 writeq(val, &ptr->pic.p_int_ate_ram[ate_index]); 256 break; 257 default: 258 panic 259 ("pcireg_int_ate_set: unknown bridgetype bridge 0x%p", 260 ptr); 261 } 262 } 263} 264 265u64 __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index) 266{ 267 union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; 268 u64 __iomem *ret = NULL; 269 270 if (pcibus_info) { 271 switch (pcibus_info->pbi_bridge_type) { 272 case PCIBR_BRIDGETYPE_TIOCP: 273 ret = &ptr->tio.cp_int_ate_ram[ate_index]; 274 break; 275 case PCIBR_BRIDGETYPE_PIC: 276 ret = &ptr->pic.p_int_ate_ram[ate_index]; 277 break; 278 default: 279 panic 280 ("pcireg_int_ate_addr: unknown bridgetype bridge 0x%p", 281 ptr); 282 } 283 } 284 return ret; 285} 286