From 3fb14811ace15adf95a9ae38922d32bf50b8cc63 Mon Sep 17 00:00:00 2001 From: Miao Wang Date: Tue, 13 Aug 2024 22:33:01 +0800 Subject: [PATCH] loongarch: fix HT_RX_INT_TRANS register On machines with legacy firmware with BPI01000 version, the HT_RX_INT_TRANS register on the node 5, i.e. the node connected with the second LS7A bridge chip, is not initialized correctly, causing the failure of the delivery of interrupts from PCIe devices connected to the second LS7A bridge chip. This patch fixes this by correctly pointing the HT_RX_INT_TRANS register to the EXT_IOI_SEND_OFF register on the corresponding node. --- arch/loongarch/kernel/legacy_boot.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/loongarch/kernel/legacy_boot.c b/arch/loongarch/kernel/legacy_boot.c index 2888e2b9fb4566..204b33109f37db 100644 --- a/arch/loongarch/kernel/legacy_boot.c +++ b/arch/loongarch/kernel/legacy_boot.c @@ -59,6 +59,16 @@ enum bpi_mem_type { #define LS7A_DMA_NODE_ID_OFFSET_SHF 8 #define LS7A_DMA_NODE_ID_OFFSET_MASK GENMASK(12, 8) +/* Section 14.4.1, Page 100 of Loongson-3A5000 User Manual v1.03 */ +#define HT_CTRL_CFG_OFF 0xfdfb000000ull +/* Section 14.5.34, Page 141 of Loongson-3A5000 User Manual v1.03 */ +#define HT_CTRL_HT_RX_INT_TRANS_LO_OFF 0x270 +#define HT_CTRL_HT_RX_INT_TRANS_HI_OFF 0x274 +#define HT_CTRL_HT_RX_INT_TRANS_INT_TRANS_ALLOW BIT(30) + +/* Section 11.2.3, Page 61 of Loongson-3A5000 User Manual v1.03 */ +#define EXT_IOI_SEND_OFF 0x1140 + struct loongarch_bpi_mem_map { struct loongarch_bpi_ext_hdr header; /*{"M", "E", "M"}*/ u8 map_count; @@ -615,6 +625,20 @@ static void __init init_acpi_arch_os_table_override (struct acpi_table_header *e writel(dma_cfg, dma_node_id_addr); } } + + // Override HT_RX_INT_TRANS + for(int i = 0; i < io_apic_count; i++){ + unsigned int node = eio_pics[i].node; + void __iomem *ht_rx_int_trans_hi = (void __iomem *) TO_UNCACHE(nid_to_addrbase(node) + HT1LO_OFFSET + HT_CTRL_CFG_OFF + HT_CTRL_HT_RX_INT_TRANS_HI_OFF); + void __iomem *ht_rx_int_trans_lo = (void __iomem *) TO_UNCACHE(nid_to_addrbase(node) + HT1LO_OFFSET + HT_CTRL_CFG_OFF + HT_CTRL_HT_RX_INT_TRANS_LO_OFF); + u64 ext_ioi_addr = nid_to_addrbase(node) + LOONGSON_REG_BASE + EXT_IOI_SEND_OFF; + u64 ht_rx_int_trans_cfg_orig = ((u64)readl(ht_rx_int_trans_hi) << 32) | readl(ht_rx_int_trans_lo); + u32 ht_rx_int_trans_cfg_hi = HT_CTRL_HT_RX_INT_TRANS_INT_TRANS_ALLOW | (ext_ioi_addr >> 32); + u32 ht_rx_int_trans_cfg_lo = ext_ioi_addr & GENMASK(31, 0); + pr_info("BPI: HT controller on node %u RX_INT_TRANS is 0x%llx, will set to 0x%llx\n", node, ht_rx_int_trans_cfg_orig, ((u64)ht_rx_int_trans_cfg_hi << 32) | ht_rx_int_trans_cfg_lo); + writel(ht_rx_int_trans_cfg_hi, ht_rx_int_trans_hi); + writel(ht_rx_int_trans_cfg_lo, ht_rx_int_trans_lo); + } } void acpi_arch_os_table_override (struct acpi_table_header *existing_table, struct acpi_table_header **new_table){