提交 f9317fee 编写于 作者: X Xu Chenjiao 提交者: Zheng Zengkai

sw64: pcie: enable PME and AER support

Sunway inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I56XUF

--------------------------------

Refactor PME and AER relative codes to use builtin kernel module, one
can enable this feature support via selecting CONFIG_PCIEPORTBUS=y,
CONFIG_PCIE_PME=y and CONFIG_PCIEAER=y. Since PME and AER events route
to CPU by MSI mechanism has been hardcoded and lack of flexibility,
we use PCI INTx mechanism to handle these events.
Signed-off-by: NXu Chenjiao <xuchenjiao@wxiat.com>
Signed-off-by: NGu Zitao <guzitao@wxiat.com>
Acked-by: NXie XiuQi <xiexiuqi@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 dda7be06
......@@ -95,6 +95,7 @@ config SW64
select DMA_OPS if PCI
select HAVE_REGS_AND_STACK_ACCESS_API
select ARCH_HAS_PTE_SPECIAL
select HARDIRQS_SW_RESEND
config LOCKDEP_SUPPORT
def_bool y
......
......@@ -412,14 +412,17 @@ static int chip3_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
struct pci_controller *hose = dev->sysdata;
return hose->int_irq;
if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
return hose->service_irq;
else
return hose->int_irq;
}
extern struct pci_controller *hose_head, **hose_tail;
static void sw6_handle_intx(unsigned int offset)
{
struct pci_controller *hose;
unsigned long value;
unsigned long value, pme_value, aer_value;
hose = hose_head;
for (hose = hose_head; hose; hose = hose->next) {
......@@ -431,6 +434,18 @@ static void sw6_handle_intx(unsigned int offset)
value = value | (1UL << 62);
write_piu_ior0(hose->node, hose->index, INTACONFIG + (offset << 7), value);
}
pme_value = read_piu_ior0(hose->node, hose->index, PMEINTCONFIG);
aer_value = read_piu_ior0(hose->node, hose->index, AERERRINTCONFIG);
if ((pme_value >> 63) || (aer_value >> 63)) {
handle_irq(hose->service_irq);
if (pme_value >> 63)
write_piu_ior0(hose->node, hose->index, PMEINTCONFIG, pme_value);
if (aer_value >> 63)
write_piu_ior0(hose->node, hose->index, AERERRINTCONFIG, aer_value);
}
if (hose->iommu_enable) {
value = read_piu_ior0(hose->node, hose->index, IOMMUEXCPT_STATUS);
if (value >> 63)
......@@ -454,76 +469,6 @@ static void chip3_device_interrupt(unsigned long irq_info)
}
}
static void set_devint_wken(int node, int val)
{
sw64_io_write(node, DEVINT_WKEN, val);
sw64_io_write(node, DEVINTWK_INTEN, 0x0);
}
static void clear_rc_status(int node, int rc)
{
unsigned int val, status;
val = 0x10000;
do {
write_rc_conf(node, rc, RC_STATUS, val);
mb();
status = read_rc_conf(node, rc, RC_STATUS);
} while (status >> 16);
}
static void chip3_suspend(int wake)
{
unsigned long val;
unsigned int val_32;
unsigned long rc_start;
int node, rc, index, cpus;
cpus = chip3_get_cpu_nums();
for (node = 0; node < cpus; node++) {
rc = -1;
rc_start = sw64_io_read(node, IO_START);
index = ffs(rc_start);
while (index) {
rc += index;
if (wake) {
val_32 = read_rc_conf(node, rc, RC_CONTROL);
val_32 &= ~0x8;
write_rc_conf(node, rc, RC_CONTROL, val_32);
set_devint_wken(node, 0x0);
val = 0x8000000000000000UL;
write_piu_ior0(node, rc, PMEINTCONFIG, val);
write_piu_ior0(node, rc, PMEMSICONFIG, val);
clear_rc_status(node, rc);
} else {
val_32 = read_rc_conf(node, rc, RC_CONTROL);
val_32 |= 0x8;
write_rc_conf(node, rc, RC_CONTROL, val_32);
clear_rc_status(node, rc);
set_devint_wken(node, 0x1f0);
#ifdef CONFIG_PCI_MSI //USE MSI
val_32 = read_rc_conf(node, rc, RC_COMMAND);
val_32 |= 0x400;
write_rc_conf(node, rc, RC_COMMAND, val_32);
val_32 = read_rc_conf(node, rc, RC_MSI_CONTROL);
val_32 |= 0x10000;
write_rc_conf(node, rc, RC_MSI_CONTROL, val_32);
val = 0x4000000000000000UL;
write_piu_ior0(node, rc, PMEMSICONFIG, val);
#else //USE INT
val = 0x4000000000000400UL;
write_piu_ior0(node, rc, PMEINTCONFIG, val);
#endif
}
rc_start = rc_start >> index;
index = ffs(rc_start);
}
}
}
static void chip3_hose_init(struct pci_controller *hose)
{
unsigned long pci_io_base;
......@@ -605,7 +550,6 @@ static struct sw64_chip_init_ops chip3_chip_init_ops = {
static struct sw64_chip_ops chip3_chip_ops = {
.get_cpu_num = chip3_get_cpu_nums,
.suspend = chip3_suspend,
.fixup = chip3_ops_fixup,
};
......@@ -784,14 +728,16 @@ static void chip3_pci_fixup_root_complex(struct pci_dev *dev)
}
dev->class &= 0xff;
dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
dev->class |= PCI_CLASS_BRIDGE_PCI << 8;
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
dev->resource[i].start = 0;
dev->resource[i].end = 0;
dev->resource[i].flags = 0;
dev->resource[i].flags = IORESOURCE_PCI_FIXED;
}
}
atomic_inc(&dev->enable_cnt);
dev->no_msi = 1;
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_JN, PCI_DEVICE_ID_CHIP3, chip3_pci_fixup_root_complex);
......@@ -69,6 +69,9 @@
#define DLI_PHY_CTL (0x10UL << 24)
#define PCI_VT_LEGACY_IO (IO_BASE | PCI_BASE | PCI_LEGACY_IO)
#define PME_ENABLE_INTD_CORE0 (0x1UL << 62 | 0x1UL << 10)
#define AER_ENABLE_INTD_CORE0 (0x1UL << 62 | 0x1UL << 10)
/*-----------------------addr-----------------------*/
/* CAB0 REG */
enum {
......
......@@ -41,6 +41,7 @@ struct pci_controller {
unsigned long node;
DECLARE_BITMAP(piu_msiconfig, 256);
int int_irq;
int service_irq;
/* For compatibility with current (as of July 2003) pciutils
* and XFree86. Eventually will be removed.
*/
......
......@@ -605,6 +605,16 @@ sw64_init_host(unsigned long node, unsigned long index)
}
}
static void set_devint_wken(int node)
{
unsigned long val;
/* enable INTD wakeup */
val = 0x80;
sw64_io_write(node, DEVINT_WKEN, val);
sw64_io_write(node, DEVINTWK_INTEN, val);
}
void __init sw64_init_arch(void)
{
if (IS_ENABLED(CONFIG_PCI)) {
......@@ -617,6 +627,7 @@ void __init sw64_init_arch(void)
cpu_num = sw64_chip->get_cpu_num();
for (node = 0; node < cpu_num; node++) {
set_devint_wken(node);
rc_enable = sw64_chip_init->pci_init.get_rc_enable(node);
if (rc_enable == 0) {
printk("PCIe is disabled on node %ld\n", node);
......@@ -658,11 +669,13 @@ static void __init sw64_init_intx(struct pci_controller *hose)
val_node = next_node_in(node, node_online_map);
else
val_node = node;
irq = irq_alloc_descs_from(NR_IRQS_LEGACY, 1, val_node);
irq = irq_alloc_descs_from(NR_IRQS_LEGACY, 2, val_node);
WARN_ON(irq < 0);
irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_level_irq);
irq_set_status_flags(irq, IRQ_LEVEL);
hose->int_irq = irq;
irq_set_chip_and_handler(irq + 1, &dummy_irq_chip, handle_level_irq);
hose->service_irq = irq + 1;
rcid = cpu_to_rcid(0);
printk_once(KERN_INFO "INTx are directed to node %d core %d.\n",
......@@ -670,6 +683,9 @@ static void __init sw64_init_intx(struct pci_controller *hose)
int_conf = 1UL << 62 | rcid; /* rebase all intx on the first logical cpu */
if (sw64_chip_init->pci_init.set_intx)
sw64_chip_init->pci_init.set_intx(node, index, int_conf);
write_piu_ior0(node, index, PMEINTCONFIG, PME_ENABLE_INTD_CORE0);
write_piu_ior0(node, index, AERERRINTCONFIG, AER_ENABLE_INTD_CORE0);
}
void __init sw64_init_irq(void)
......
......@@ -33,20 +33,14 @@ void sw64_suspend_enter(void)
*/
disable_local_timer();
#ifdef CONFIG_PCI
if (sw64_chip->suspend)
sw64_chip->suspend(0);
#endif
#ifdef CONFIG_SW64_SUSPEND_DEEPSLEEP_BOOTCORE
sw64_suspend_deep_sleep(&suspend_state);
#else
mtinten();
asm("halt");
#endif
#ifdef CONFIG_PCI
if (sw64_chip->suspend)
sw64_chip->suspend(1);
#endif
disable_local_timer();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册