From patchwork Fri Apr 3 09:29:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tiezhu Yang X-Patchwork-Id: 11472311 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 080151805 for ; Fri, 3 Apr 2020 09:30:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E51B52073B for ; Fri, 3 Apr 2020 09:30:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2390505AbgDCJaH (ORCPT ); Fri, 3 Apr 2020 05:30:07 -0400 Received: from mail.loongson.cn ([114.242.206.163]:42908 "EHLO loongson.cn" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727431AbgDCJaG (ORCPT ); Fri, 3 Apr 2020 05:30:06 -0400 Received: from linux.localdomain (unknown [113.200.148.30]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxX2gQAodeHGAjAA--.150S3; Fri, 03 Apr 2020 17:29:58 +0800 (CST) From: Tiezhu Yang To: Thomas Bogendoerfer , Huacai Chen , Jiaxun Yang Cc: linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, Xuefeng Li Subject: [PATCH v4 1/3] MIPS: Loongson: Get host bridge information Date: Fri, 3 Apr 2020 17:29:49 +0800 Message-Id: <1585906191-26037-2-git-send-email-yangtiezhu@loongson.cn> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1585906191-26037-1-git-send-email-yangtiezhu@loongson.cn> References: <1585906191-26037-1-git-send-email-yangtiezhu@loongson.cn> X-CM-TRANSID: AQAAf9DxX2gQAodeHGAjAA--.150S3 X-Coremail-Antispam: 1UD129KBjvJXoWxCryDAr1DCF4UZw1UZw43Wrg_yoW5ZFW3pa 9Fyw15Grs5Wr13ur4fArWj9r13Aan5tFW3WFW2gw1Y9r9xXw1YqFsYkF18Zr17AF45Ga48 Xasagr48GF17Cw7anT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUU9m14x267AKxVW8JVW5JwAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_Jr4l82xGYIkIc2 x26xkF7I0E14v26r1I6r4UM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Xr0_Ar1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UM2 8EF7xvwVC2z280aVAFwI0_Cr1j6rxdM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS 0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2 IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0 Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCF04k20xvY0x0EwIxGrwCFx2 IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v2 6r106r1rMI8E67AF67kF1VAFwI0_JF0_Jw1lIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67 AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IY s7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr 0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0JU39NfUUUUU= X-CM-SenderInfo: p1dqw3xlh2x3gn0dqz5rrqw2lrqou0/ Sender: linux-mips-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mips@vger.kernel.org Read the address of host bridge configuration space to get the vendor ID and device ID of host bridge, and then we can distinguish various types of host bridge such as LS7A or RS780E. Signed-off-by: Tiezhu Yang Reviewed-by: Jiaxun Yang --- v3: - Modify the macro definition HOST_BRIDGE_CONFIG_ADDR and add comment to make it easy to read. - Use PCI_VENDOR_ID_LOONGSON in pci_ids.h instead of 0x0014 PCI_VENDOR_ID_LOONGSON depends on the mainline tree's commit: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9acb9fe18d86 v4: - Use LS7A instead of Loongson 7A1000 in the description - Use LS7A or ls7a instead of LS7A1000 or ls7a1000 in the code arch/mips/include/asm/mach-loongson64/boot_param.h | 6 ++++++ arch/mips/loongson64/env.c | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h index 2ed483e..fc9f14b 100644 --- a/arch/mips/include/asm/mach-loongson64/boot_param.h +++ b/arch/mips/include/asm/mach-loongson64/boot_param.h @@ -192,6 +192,11 @@ struct boot_params { struct efi_reset_system_t reset_system; }; +enum loongson_bridge_type { + RS780E = 1, + LS7A = 2 +}; + struct loongson_system_configuration { u32 nr_cpus; u32 nr_nodes; @@ -200,6 +205,7 @@ struct loongson_system_configuration { u16 boot_cpu_id; u16 reserved_cpus_mask; enum loongson_cpu_type cputype; + enum loongson_bridge_type bridgetype; u64 ht_control_base; u64 pci_mem_start_addr; u64 pci_mem_end_addr; diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c index 2554ef1..71f4aaf 100644 --- a/arch/mips/loongson64/env.c +++ b/arch/mips/loongson64/env.c @@ -14,12 +14,15 @@ * Author: Wu Zhangjin, wuzhangjin@gmail.com */ #include +#include #include #include #include #include #include +#define HOST_BRIDGE_CONFIG_ADDR ((void __iomem *)TO_UNCAC(0x1a000000)) + u32 cpu_clock_freq; EXPORT_SYMBOL(cpu_clock_freq); struct efi_memory_map_loongson *loongson_memmap; @@ -43,6 +46,8 @@ void __init prom_init_env(void) struct system_loongson *esys; struct efi_cpuinfo_loongson *ecpu; struct irq_source_routing_table *eirq_source; + u32 id; + u16 vendor, device; /* firmware arguments are initialized in head.S */ boot_p = (struct boot_params *)fw_arg2; @@ -178,4 +183,17 @@ void __init prom_init_env(void) memcpy(loongson_sysconf.sensors, esys->sensors, sizeof(struct sensor_device) * loongson_sysconf.nr_sensors); pr_info("CpuClock = %u\n", cpu_clock_freq); + + /* Read the ID of PCI host bridge to detect bridge type */ + id = readl(HOST_BRIDGE_CONFIG_ADDR); + vendor = id & 0xffff; + device = (id >> 16) & 0xffff; + + if (vendor == PCI_VENDOR_ID_LOONGSON && device == 0x7a00) { + pr_info("The bridge chip is LS7A\n"); + loongson_sysconf.bridgetype = LS7A; + } else { + pr_info("The bridge chip is RS780E or SR5690\n"); + loongson_sysconf.bridgetype = RS780E; + } } From patchwork Fri Apr 3 09:29:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tiezhu Yang X-Patchwork-Id: 11472309 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6AAB21805 for ; Fri, 3 Apr 2020 09:30:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 497EF20787 for ; Fri, 3 Apr 2020 09:30:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2390554AbgDCJaH (ORCPT ); Fri, 3 Apr 2020 05:30:07 -0400 Received: from mail.loongson.cn ([114.242.206.163]:42932 "EHLO loongson.cn" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727774AbgDCJaG (ORCPT ); Fri, 3 Apr 2020 05:30:06 -0400 Received: from linux.localdomain (unknown [113.200.148.30]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxX2gQAodeHGAjAA--.150S4; Fri, 03 Apr 2020 17:30:00 +0800 (CST) From: Tiezhu Yang To: Thomas Bogendoerfer , Huacai Chen , Jiaxun Yang Cc: linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, Xuefeng Li Subject: [PATCH v4 2/3] MIPS: Loongson: Add DMA support for LS7A Date: Fri, 3 Apr 2020 17:29:50 +0800 Message-Id: <1585906191-26037-3-git-send-email-yangtiezhu@loongson.cn> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1585906191-26037-1-git-send-email-yangtiezhu@loongson.cn> References: <1585906191-26037-1-git-send-email-yangtiezhu@loongson.cn> X-CM-TRANSID: AQAAf9DxX2gQAodeHGAjAA--.150S4 X-Coremail-Antispam: 1UD129KBjvJXoW3Gw1xZF4rCFW3ZrWrGw1UGFg_yoW7ZrWUpa y7A3Z5Gr45WF1xurZ3Ary8uryrAFsxKFs7JF42gr4Y9as8X34FvFs7CFn5Xr17Ar4kX3Wx ZFyFgrWxWF1xCrJanT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUU9m14x267AKxVW5JVWrJwAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_Jryl82xGYIkIc2 x26xkF7I0E14v26r4j6ryUM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Xr0_Ar1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UM2 8EF7xvwVC2z280aVAFwI0_Cr1j6rxdM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS 0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2 IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0 Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCF04k20xvY0x0EwIxGrwCFx2 IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v2 6r106r1rMI8E67AF67kF1VAFwI0_JF0_Jw1lIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67 AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IY s7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr 0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0JU0Lv_UUUUU= X-CM-SenderInfo: p1dqw3xlh2x3gn0dqz5rrqw2lrqou0/ Sender: linux-mips-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mips@vger.kernel.org In the current market, the most used bridge chip on the Loongson platform are RS780E and LS7A, the RS780E bridge chip is already supported by the mainline kernel. If use the default implementation of __phys_to_dma() and __dma_to_phys() in dma-direct.h when CONFIG_ARCH_HAS_PHYS_TO_DMA is not set, it works well used with LS7A on the Loongson single-way and multi-way platform, and also works well used with RS780E on the Loongson single-way platform, but the DMA address will be wrong on the non-node0 used with RS780E on the Loongson multi-way platform. Just as the description in the code comment, the devices get node id from 40 bit of HyperTransport bus, so we extract 2 bit node id (bit 44~45) from 48 bit address space of Loongson CPU and embed it into HyperTransport bus (bit 37-38), this operation can be done only at the software level used with RS780E on the Loongson multi-way platform, because it has no hardware function to translate address of node id, this is a hardware compatibility problem. Device | | DMA address | Host Bridge | | HT bus address (40 bit) | CPU | | physical address (48 bit) | RAM The LS7A has dma_node_id_offset field in the DMA route config register, the hardware can use the dma_node_id_offset to translate address of node id automatically, so we can get correct address when just use the dma_pfn_offset field in struct device. For the above reasons, in order to maintain downward compatibility to support the RS780E bridge chip, it is better to use the platform dependent implementation of __phys_to_dma() and __dma_to_phys(). Signed-off-by: Tiezhu Yang --- v3: - Modify the macro definition NODE_ID_OFFSET_ADDR to make it easy to read - update the commit message v4: - Use LS7A instead of Loongson 7A1000 in the description - Use LS7A or ls7a instead of LS7A1000 or ls7a1000 in the code arch/mips/include/asm/mach-loongson64/boot_param.h | 5 +++++ arch/mips/loongson64/dma.c | 9 ++++++--- arch/mips/loongson64/env.c | 2 ++ arch/mips/loongson64/init.c | 17 +++++++++++++++++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h index fc9f14b..4ac7034 100644 --- a/arch/mips/include/asm/mach-loongson64/boot_param.h +++ b/arch/mips/include/asm/mach-loongson64/boot_param.h @@ -221,9 +221,14 @@ struct loongson_system_configuration { u32 nr_sensors; struct sensor_device sensors[MAX_SENSORS]; u64 workarounds; + void (*early_config)(void); }; extern struct efi_memory_map_loongson *loongson_memmap; extern struct loongson_system_configuration loongson_sysconf; +extern u32 node_id_offset; +extern void rs780e_early_config(void); +extern void ls7a_early_config(void); + #endif diff --git a/arch/mips/loongson64/dma.c b/arch/mips/loongson64/dma.c index 5e86635..dbfe6e8 100644 --- a/arch/mips/loongson64/dma.c +++ b/arch/mips/loongson64/dma.c @@ -2,21 +2,24 @@ #include #include #include +#include dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr) { /* We extract 2bit node id (bit 44~47, only bit 44~45 used now) from * Loongson-3's 48bit address space and embed it into 40bit */ long nid = (paddr >> 44) & 0x3; - return ((nid << 44) ^ paddr) | (nid << 37); + + return ((nid << 44) ^ paddr) | (nid << node_id_offset); } phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr) { /* We extract 2bit node id (bit 44~47, only bit 44~45 used now) from * Loongson-3's 48bit address space and embed it into 40bit */ - long nid = (daddr >> 37) & 0x3; - return ((nid << 37) ^ daddr) | (nid << 44); + long nid = (daddr >> node_id_offset) & 0x3; + + return ((nid << node_id_offset) ^ daddr) | (nid << 44); } void __init plat_swiotlb_setup(void) diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c index 71f4aaf..d11bc34 100644 --- a/arch/mips/loongson64/env.c +++ b/arch/mips/loongson64/env.c @@ -192,8 +192,10 @@ void __init prom_init_env(void) if (vendor == PCI_VENDOR_ID_LOONGSON && device == 0x7a00) { pr_info("The bridge chip is LS7A\n"); loongson_sysconf.bridgetype = LS7A; + loongson_sysconf.early_config = ls7a_early_config; } else { pr_info("The bridge chip is RS780E or SR5690\n"); loongson_sysconf.bridgetype = RS780E; + loongson_sysconf.early_config = rs780e_early_config; } } diff --git a/arch/mips/loongson64/init.c b/arch/mips/loongson64/init.c index da38944..06625d6 100644 --- a/arch/mips/loongson64/init.c +++ b/arch/mips/loongson64/init.c @@ -13,6 +13,11 @@ #include #include +#include + +#define NODE_ID_OFFSET_ADDR ((void __iomem *)TO_UNCAC(0x1001041c)) + +u32 node_id_offset; static void __init mips_nmi_setup(void) { @@ -24,6 +29,16 @@ static void __init mips_nmi_setup(void) flush_icache_range((unsigned long)base, (unsigned long)base + 0x80); } +void rs780e_early_config(void) +{ + node_id_offset = 37; +} + +void ls7a_early_config(void) +{ + node_id_offset = ((readl(NODE_ID_OFFSET_ADDR) >> 8) & 0x1f) + 36; +} + void __init prom_init(void) { fw_init_cmdline(); @@ -33,6 +48,8 @@ void __init prom_init(void) set_io_port_base((unsigned long) ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE)); + loongson_sysconf.early_config(); + prom_init_numa_memory(); /* Hardcode to CPU UART 0 */ From patchwork Fri Apr 3 09:29:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tiezhu Yang X-Patchwork-Id: 11472305 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 72D651874 for ; Fri, 3 Apr 2020 09:30:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4E8092073B for ; Fri, 3 Apr 2020 09:30:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389015AbgDCJaG (ORCPT ); Fri, 3 Apr 2020 05:30:06 -0400 Received: from mail.loongson.cn ([114.242.206.163]:42998 "EHLO loongson.cn" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2390255AbgDCJaG (ORCPT ); Fri, 3 Apr 2020 05:30:06 -0400 Received: from linux.localdomain (unknown [113.200.148.30]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9DxX2gQAodeHGAjAA--.150S5; Fri, 03 Apr 2020 17:30:01 +0800 (CST) From: Tiezhu Yang To: Thomas Bogendoerfer , Huacai Chen , Jiaxun Yang Cc: linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, Xuefeng Li Subject: [PATCH v4 3/3] MIPS: Loongson: Add PCI support for LS7A Date: Fri, 3 Apr 2020 17:29:51 +0800 Message-Id: <1585906191-26037-4-git-send-email-yangtiezhu@loongson.cn> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1585906191-26037-1-git-send-email-yangtiezhu@loongson.cn> References: <1585906191-26037-1-git-send-email-yangtiezhu@loongson.cn> X-CM-TRANSID: AQAAf9DxX2gQAodeHGAjAA--.150S5 X-Coremail-Antispam: 1UD129KBjvJXoW3Jw18tw45ZFykKr4kXrW5Jrb_yoWxCw18pF 43A3WUKr4FqFn3GF9Yy3y8GF1rAFZxJF97KFW2y34j93sxZryFqF95W3W5tr4fKw4DXa4x W3yfKF4UGF1jk3JanT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUU9m14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JrWl82xGYIkIc2 x26xkF7I0E14v26r4j6ryUM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Xr0_Ar1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UM2 8EF7xvwVC2z280aVAFwI0_Cr1j6rxdM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS 0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2 IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0 Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCF04k20xvY0x0EwIxGrwCFx2 IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v2 6r106r1rMI8E67AF67kF1VAFwI0_JF0_Jw1lIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67 AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IY s7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr 0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0JU5wIkUUUUU= X-CM-SenderInfo: p1dqw3xlh2x3gn0dqz5rrqw2lrqou0/ Sender: linux-mips-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mips@vger.kernel.org Add PCI support for LS7A to detect PCI device. Signed-off-by: Tiezhu Yang --- v3: - Move ls7a1000_pci_class_quirk() to fixup-loongson3.c - Use PCI_VENDOR_ID_LOONGSON in pci_ids.h instead of 0x0014 PCI_VENDOR_ID_LOONGSON depends on the mainline tree's commit: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9acb9fe18d86 v4: - Use LS7A instead of Loongson 7A1000 in the description - Use LS7A or ls7a instead of LS7A1000 or ls7a1000 in the code arch/mips/include/asm/mach-loongson64/boot_param.h | 9 ++++ arch/mips/loongson64/env.c | 2 + arch/mips/pci/fixup-loongson3.c | 12 +++++ arch/mips/pci/ops-loongson3.c | 63 ++++++++++++++++++++-- 4 files changed, 82 insertions(+), 4 deletions(-) diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h index 4ac7034..02dcdf2 100644 --- a/arch/mips/include/asm/mach-loongson64/boot_param.h +++ b/arch/mips/include/asm/mach-loongson64/boot_param.h @@ -197,6 +197,7 @@ enum loongson_bridge_type { LS7A = 2 }; +struct pci_bus; struct loongson_system_configuration { u32 nr_cpus; u32 nr_nodes; @@ -222,6 +223,8 @@ struct loongson_system_configuration { struct sensor_device sensors[MAX_SENSORS]; u64 workarounds; void (*early_config)(void); + int (*pci_config_access)(unsigned char access_type, struct pci_bus *bus, + unsigned int devfn, int where, u32 *data); }; extern struct efi_memory_map_loongson *loongson_memmap; @@ -230,5 +233,11 @@ extern struct loongson_system_configuration loongson_sysconf; extern u32 node_id_offset; extern void rs780e_early_config(void); extern void ls7a_early_config(void); +extern int rs780e_pci_config_access(unsigned char access_type, + struct pci_bus *bus, unsigned int devfn, + int where, u32 *data); +extern int ls7a_pci_config_access(unsigned char access_type, + struct pci_bus *bus, unsigned int devfn, + int where, u32 *data); #endif diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c index d11bc34..9b206ed 100644 --- a/arch/mips/loongson64/env.c +++ b/arch/mips/loongson64/env.c @@ -193,9 +193,11 @@ void __init prom_init_env(void) pr_info("The bridge chip is LS7A\n"); loongson_sysconf.bridgetype = LS7A; loongson_sysconf.early_config = ls7a_early_config; + loongson_sysconf.pci_config_access = ls7a_pci_config_access; } else { pr_info("The bridge chip is RS780E or SR5690\n"); loongson_sysconf.bridgetype = RS780E; loongson_sysconf.early_config = rs780e_early_config; + loongson_sysconf.pci_config_access = rs780e_pci_config_access; } } diff --git a/arch/mips/pci/fixup-loongson3.c b/arch/mips/pci/fixup-loongson3.c index 8a741c2..6e7514c 100644 --- a/arch/mips/pci/fixup-loongson3.c +++ b/arch/mips/pci/fixup-loongson3.c @@ -64,6 +64,18 @@ static void pci_fixup_radeon(struct pci_dev *pdev) DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_radeon); +static void ls7a_pci_class_quirk(struct pci_dev *dev) +{ + dev->class = PCI_CLASS_BRIDGE_PCI << 8; +} + +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON, 0x7a09, + ls7a_pci_class_quirk); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON, 0x7a19, + ls7a_pci_class_quirk); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON, 0x7a29, + ls7a_pci_class_quirk); + /* Do platform specific device initialization at pci_enable_device() time */ int pcibios_plat_dev_init(struct pci_dev *dev) { diff --git a/arch/mips/pci/ops-loongson3.c b/arch/mips/pci/ops-loongson3.c index 2f6ad36..fba55dd 100644 --- a/arch/mips/pci/ops-loongson3.c +++ b/arch/mips/pci/ops-loongson3.c @@ -13,7 +13,10 @@ #define HT1LO_PCICFG_BASE 0x1a000000 #define HT1LO_PCICFG_BASE_TP1 0x1b000000 -static int loongson3_pci_config_access(unsigned char access_type, +#define HT1LO_PCICFG_BASE_EXT 0xefe00000000 +#define HT1LO_PCICFG_BASE_TP1_EXT 0xefe10000000 + +int rs780e_pci_config_access(unsigned char access_type, struct pci_bus *bus, unsigned int devfn, int where, u32 *data) { @@ -62,11 +65,63 @@ static int loongson3_pci_config_access(unsigned char access_type, return PCIBIOS_SUCCESSFUL; } + +int ls7a_pci_config_access(unsigned char access_type, + struct pci_bus *bus, unsigned int devfn, + int where, u32 *data) +{ + u_int64_t addr; + void *addrp; + unsigned char busnum = bus->number; + int device = PCI_SLOT(devfn); + int function = PCI_FUNC(devfn); + int reg = where & ~3; + + if (where >= PCI_CFG_SPACE_EXP_SIZE) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (busnum == 0 && device > 23) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (where < PCI_CFG_SPACE_SIZE) { /* standard config */ + addr = (busnum << 16) | (device << 11) | (function << 8) | reg; + if (busnum == 0) { + addr = HT1LO_PCICFG_BASE | addr; + addrp = (void *)TO_UNCAC(addr); + } else { + addr = HT1LO_PCICFG_BASE_TP1 | addr; + addrp = (void *)TO_UNCAC(addr); + } + } else { /* extended config */ + reg = (reg & 0xff) | ((reg & 0xf00) << 16); + addr = (busnum << 16) | (device << 11) | (function << 8) | reg; + if (busnum == 0) { + addr = HT1LO_PCICFG_BASE_EXT | addr; + addrp = (void *)TO_UNCAC(addr); + } else { + addr = HT1LO_PCICFG_BASE_TP1_EXT | addr; + addrp = (void *)TO_UNCAC(addr); + } + } + + if (access_type == PCI_ACCESS_WRITE) + *(unsigned int *)addrp = cpu_to_le32(*data); + else { + *data = le32_to_cpu(*(unsigned int *)addrp); + if (*data == 0xffffffff) { + *data = -1; + return PCIBIOS_DEVICE_NOT_FOUND; + } + } + + return PCIBIOS_SUCCESSFUL; +} + static int loongson3_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) { u32 data = 0; - int ret = loongson3_pci_config_access(PCI_ACCESS_READ, + int ret = loongson_sysconf.pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data); if (ret != PCIBIOS_SUCCESSFUL) @@ -91,7 +146,7 @@ static int loongson3_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn, if (size == 4) data = val; else { - ret = loongson3_pci_config_access(PCI_ACCESS_READ, + ret = loongson_sysconf.pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data); if (ret != PCIBIOS_SUCCESSFUL) return ret; @@ -104,7 +159,7 @@ static int loongson3_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn, (val << ((where & 3) << 3)); } - ret = loongson3_pci_config_access(PCI_ACCESS_WRITE, + ret = loongson_sysconf.pci_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data); return ret;