You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
285 lines
7.2 KiB
285 lines
7.2 KiB
/*
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file "COPYING" in the main directory of this archive
|
|
* for more details.
|
|
*
|
|
* Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/interrupt.h>
|
|
#include <linux/types.h>
|
|
#include <asm/sn/io.h>
|
|
#include <asm/sn/pcibr_provider.h>
|
|
#include <asm/sn/pcibus_provider_defs.h>
|
|
#include <asm/sn/pcidev.h>
|
|
#include <asm/sn/pic.h>
|
|
#include <asm/sn/tiocp.h>
|
|
|
|
union br_ptr {
|
|
struct tiocp tio;
|
|
struct pic pic;
|
|
};
|
|
|
|
/*
|
|
* Control Register Access -- Read/Write 0000_0020
|
|
*/
|
|
void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, u64 bits)
|
|
{
|
|
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
|
|
|
if (pcibus_info) {
|
|
switch (pcibus_info->pbi_bridge_type) {
|
|
case PCIBR_BRIDGETYPE_TIOCP:
|
|
__sn_clrq_relaxed(&ptr->tio.cp_control, bits);
|
|
break;
|
|
case PCIBR_BRIDGETYPE_PIC:
|
|
__sn_clrq_relaxed(&ptr->pic.p_wid_control, bits);
|
|
break;
|
|
default:
|
|
panic
|
|
("pcireg_control_bit_clr: unknown bridgetype bridge 0x%p",
|
|
ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
void pcireg_control_bit_set(struct pcibus_info *pcibus_info, u64 bits)
|
|
{
|
|
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
|
|
|
if (pcibus_info) {
|
|
switch (pcibus_info->pbi_bridge_type) {
|
|
case PCIBR_BRIDGETYPE_TIOCP:
|
|
__sn_setq_relaxed(&ptr->tio.cp_control, bits);
|
|
break;
|
|
case PCIBR_BRIDGETYPE_PIC:
|
|
__sn_setq_relaxed(&ptr->pic.p_wid_control, bits);
|
|
break;
|
|
default:
|
|
panic
|
|
("pcireg_control_bit_set: unknown bridgetype bridge 0x%p",
|
|
ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* PCI/PCIX Target Flush Register Access -- Read Only 0000_0050
|
|
*/
|
|
u64 pcireg_tflush_get(struct pcibus_info *pcibus_info)
|
|
{
|
|
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
|
u64 ret = 0;
|
|
|
|
if (pcibus_info) {
|
|
switch (pcibus_info->pbi_bridge_type) {
|
|
case PCIBR_BRIDGETYPE_TIOCP:
|
|
ret = __sn_readq_relaxed(&ptr->tio.cp_tflush);
|
|
break;
|
|
case PCIBR_BRIDGETYPE_PIC:
|
|
ret = __sn_readq_relaxed(&ptr->pic.p_wid_tflush);
|
|
break;
|
|
default:
|
|
panic
|
|
("pcireg_tflush_get: unknown bridgetype bridge 0x%p",
|
|
ptr);
|
|
}
|
|
}
|
|
|
|
/* Read of the Target Flush should always return zero */
|
|
if (ret != 0)
|
|
panic("pcireg_tflush_get:Target Flush failed\n");
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Interrupt Status Register Access -- Read Only 0000_0100
|
|
*/
|
|
u64 pcireg_intr_status_get(struct pcibus_info * pcibus_info)
|
|
{
|
|
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
|
u64 ret = 0;
|
|
|
|
if (pcibus_info) {
|
|
switch (pcibus_info->pbi_bridge_type) {
|
|
case PCIBR_BRIDGETYPE_TIOCP:
|
|
ret = __sn_readq_relaxed(&ptr->tio.cp_int_status);
|
|
break;
|
|
case PCIBR_BRIDGETYPE_PIC:
|
|
ret = __sn_readq_relaxed(&ptr->pic.p_int_status);
|
|
break;
|
|
default:
|
|
panic
|
|
("pcireg_intr_status_get: unknown bridgetype bridge 0x%p",
|
|
ptr);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Interrupt Enable Register Access -- Read/Write 0000_0108
|
|
*/
|
|
void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, u64 bits)
|
|
{
|
|
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
|
|
|
if (pcibus_info) {
|
|
switch (pcibus_info->pbi_bridge_type) {
|
|
case PCIBR_BRIDGETYPE_TIOCP:
|
|
__sn_clrq_relaxed(&ptr->tio.cp_int_enable, bits);
|
|
break;
|
|
case PCIBR_BRIDGETYPE_PIC:
|
|
__sn_clrq_relaxed(&ptr->pic.p_int_enable, bits);
|
|
break;
|
|
default:
|
|
panic
|
|
("pcireg_intr_enable_bit_clr: unknown bridgetype bridge 0x%p",
|
|
ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, u64 bits)
|
|
{
|
|
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
|
|
|
if (pcibus_info) {
|
|
switch (pcibus_info->pbi_bridge_type) {
|
|
case PCIBR_BRIDGETYPE_TIOCP:
|
|
__sn_setq_relaxed(&ptr->tio.cp_int_enable, bits);
|
|
break;
|
|
case PCIBR_BRIDGETYPE_PIC:
|
|
__sn_setq_relaxed(&ptr->pic.p_int_enable, bits);
|
|
break;
|
|
default:
|
|
panic
|
|
("pcireg_intr_enable_bit_set: unknown bridgetype bridge 0x%p",
|
|
ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Intr Host Address Register (int_addr) -- Read/Write 0000_0130 - 0000_0168
|
|
*/
|
|
void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n,
|
|
u64 addr)
|
|
{
|
|
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
|
|
|
if (pcibus_info) {
|
|
switch (pcibus_info->pbi_bridge_type) {
|
|
case PCIBR_BRIDGETYPE_TIOCP:
|
|
__sn_clrq_relaxed(&ptr->tio.cp_int_addr[int_n],
|
|
TIOCP_HOST_INTR_ADDR);
|
|
__sn_setq_relaxed(&ptr->tio.cp_int_addr[int_n],
|
|
(addr & TIOCP_HOST_INTR_ADDR));
|
|
break;
|
|
case PCIBR_BRIDGETYPE_PIC:
|
|
__sn_clrq_relaxed(&ptr->pic.p_int_addr[int_n],
|
|
PIC_HOST_INTR_ADDR);
|
|
__sn_setq_relaxed(&ptr->pic.p_int_addr[int_n],
|
|
(addr & PIC_HOST_INTR_ADDR));
|
|
break;
|
|
default:
|
|
panic
|
|
("pcireg_intr_addr_addr_get: unknown bridgetype bridge 0x%p",
|
|
ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Force Interrupt Register Access -- Write Only 0000_01C0 - 0000_01F8
|
|
*/
|
|
void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n)
|
|
{
|
|
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
|
|
|
if (pcibus_info) {
|
|
switch (pcibus_info->pbi_bridge_type) {
|
|
case PCIBR_BRIDGETYPE_TIOCP:
|
|
writeq(1, &ptr->tio.cp_force_pin[int_n]);
|
|
break;
|
|
case PCIBR_BRIDGETYPE_PIC:
|
|
writeq(1, &ptr->pic.p_force_pin[int_n]);
|
|
break;
|
|
default:
|
|
panic
|
|
("pcireg_force_intr_set: unknown bridgetype bridge 0x%p",
|
|
ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Device(x) Write Buffer Flush Reg Access -- Read Only 0000_0240 - 0000_0258
|
|
*/
|
|
u64 pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device)
|
|
{
|
|
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
|
u64 ret = 0;
|
|
|
|
if (pcibus_info) {
|
|
switch (pcibus_info->pbi_bridge_type) {
|
|
case PCIBR_BRIDGETYPE_TIOCP:
|
|
ret =
|
|
__sn_readq_relaxed(&ptr->tio.cp_wr_req_buf[device]);
|
|
break;
|
|
case PCIBR_BRIDGETYPE_PIC:
|
|
ret =
|
|
__sn_readq_relaxed(&ptr->pic.p_wr_req_buf[device]);
|
|
break;
|
|
default:
|
|
panic("pcireg_wrb_flush_get: unknown bridgetype bridge 0x%p", ptr);
|
|
}
|
|
|
|
}
|
|
/* Read of the Write Buffer Flush should always return zero */
|
|
return ret;
|
|
}
|
|
|
|
void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index,
|
|
u64 val)
|
|
{
|
|
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
|
|
|
if (pcibus_info) {
|
|
switch (pcibus_info->pbi_bridge_type) {
|
|
case PCIBR_BRIDGETYPE_TIOCP:
|
|
writeq(val, &ptr->tio.cp_int_ate_ram[ate_index]);
|
|
break;
|
|
case PCIBR_BRIDGETYPE_PIC:
|
|
writeq(val, &ptr->pic.p_int_ate_ram[ate_index]);
|
|
break;
|
|
default:
|
|
panic
|
|
("pcireg_int_ate_set: unknown bridgetype bridge 0x%p",
|
|
ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
u64 __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index)
|
|
{
|
|
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
|
|
u64 __iomem *ret = NULL;
|
|
|
|
if (pcibus_info) {
|
|
switch (pcibus_info->pbi_bridge_type) {
|
|
case PCIBR_BRIDGETYPE_TIOCP:
|
|
ret = &ptr->tio.cp_int_ate_ram[ate_index];
|
|
break;
|
|
case PCIBR_BRIDGETYPE_PIC:
|
|
ret = &ptr->pic.p_int_ate_ram[ate_index];
|
|
break;
|
|
default:
|
|
panic
|
|
("pcireg_int_ate_addr: unknown bridgetype bridge 0x%p",
|
|
ptr);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|