All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] Add basic support for Loongson 7A1000 bridge chip
@ 2020-03-09  8:23 Tiezhu Yang
  2020-03-09  8:23 ` [PATCH 1/6] PCI: Add Loongson vendor ID and 7A1000 device IDs Tiezhu Yang
                   ` (5 more replies)
  0 siblings, 6 replies; 21+ messages in thread
From: Tiezhu Yang @ 2020-03-09  8:23 UTC (permalink / raw)
  To: Thomas Bogendoerfer, Huacai Chen, Jiaxun Yang, Bjorn Helgaas, Jens Axboe
  Cc: linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li

The Loongson 7A1000 bridge chip has been released for several years
since the second half of 2017, but it is not supported by the Linux
mainline kernel while it only works well with the Loongson internal
kernel version. When I update the latest version of Linux mainline
kernel on the Loongson 3A3000 CPU and 7A1000 bridge chip system,
the boot process failed and I feel depressed.

The 7A1000 bridge chip is used a lot with 3A3000 or 3A4000 CPU in
the most Loongson desktop and sever products, it is important to
support Loongson 7A1000 bridge chip by the Linux mainline kernel.

This patch series adds the basic support for the Loongson 7A1000
bridge chip, when apply these patches based on linux-5.6-rc5, the
boot process is successful and we can login normally used with the
latest firmware and discrete graphics card, the next work to do is
power management and some other controller device drivers.

Additionally, when I git clone mips code [1], the speed is too slow
and clone always failed, so this patch series is based on the latest
linux-5.6-rc5 [2].

If you have any questions and suggestions, please let me know.

Thanks,

Tiezhu Yang

[1] git clone https://git.kernel.org/pub/scm/linux/kernel/git/mips/linux.git
[2] git clone https://github.com/torvalds/linux.git

Tiezhu Yang (6):
  PCI: Add Loongson vendor ID and 7A1000 device IDs
  AHCI: Add support for Loongson 7A1000 SATA controller
  MIPS: Loongson: Use firmware arguments to get board name
  MIPS: Loongson: Add DMA support for 7A1000
  MIPS: Loongson: Add PCI support for 7A1000
  MIPS: Loongson: Add support for 7A1000 interrupt controller

 arch/mips/include/asm/mach-loongson64/boot_param.h |   2 +
 arch/mips/include/asm/mach-loongson64/ioaicu.h     | 166 +++++++++++
 arch/mips/include/asm/mach-loongson64/irq.h        |   2 +
 arch/mips/include/asm/mach-loongson64/pci.h        |   1 +
 arch/mips/loongson64/Makefile                      |   2 +-
 arch/mips/loongson64/dma.c                         |  49 +++-
 arch/mips/loongson64/env.c                         |   5 +
 arch/mips/loongson64/init.c                        |  13 +
 arch/mips/loongson64/ioaicu.c                      | 305 +++++++++++++++++++++
 arch/mips/loongson64/irq.c                         |  20 +-
 arch/mips/loongson64/pci.c                         |  12 +-
 arch/mips/loongson64/smp.c                         |  11 +-
 arch/mips/pci/Makefile                             |   2 +-
 arch/mips/pci/ops-loongson3-ls7a.c                 | 132 +++++++++
 drivers/ata/ahci.c                                 |   8 +
 include/linux/pci_ids.h                            |  18 ++
 16 files changed, 733 insertions(+), 15 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-loongson64/ioaicu.h
 create mode 100644 arch/mips/loongson64/ioaicu.c
 create mode 100644 arch/mips/pci/ops-loongson3-ls7a.c

-- 
2.1.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 1/6] PCI: Add Loongson vendor ID and 7A1000 device IDs
  2020-03-09  8:23 [PATCH 0/6] Add basic support for Loongson 7A1000 bridge chip Tiezhu Yang
@ 2020-03-09  8:23 ` Tiezhu Yang
  2020-03-09  8:50   ` 回复:[PATCH " Jiaxun Yang
  2020-03-09  8:23 ` [PATCH 2/6] AHCI: Add support for Loongson 7A1000 SATA controller Tiezhu Yang
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 21+ messages in thread
From: Tiezhu Yang @ 2020-03-09  8:23 UTC (permalink / raw)
  To: Thomas Bogendoerfer, Huacai Chen, Jiaxun Yang, Bjorn Helgaas, Jens Axboe
  Cc: linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li

Add the Loongson vendor ID and 7A1000 device IDs to pci_ids.h
to be used by the controller driver in the future.

The Loongson IDs can be found at the following link:
https://git.kernel.org/pub/scm/utils/pciutils/pciutils.git/tree/pci.ids

Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
 include/linux/pci_ids.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 352c0d7..0125ab4 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -3113,4 +3113,22 @@
 
 #define PCI_VENDOR_ID_NCUBE		0x10ff
 
+#define PCI_VENDOR_ID_LOONGSON			0x0014
+#define PCI_DEVICE_ID_LOONGSON_7A1000_HT	0x7a00
+#define PCI_DEVICE_ID_LOONGSON_7A1000_APB	0x7a02
+#define PCI_DEVICE_ID_LOONGSON_7A1000_GMAC	0x7a03
+#define PCI_DEVICE_ID_LOONGSON_7A1000_OTG	0x7a04
+#define PCI_DEVICE_ID_LOONGSON_7A1000_DC	0x7a06
+#define PCI_DEVICE_ID_LOONGSON_7A1000_HDA	0x7a07
+#define PCI_DEVICE_ID_LOONGSON_7A1000_SATA	0x7a08
+#define PCI_DEVICE_ID_LOONGSON_7A1000_PCIE_X1	0x7a09
+#define PCI_DEVICE_ID_LOONGSON_7A1000_SPI	0x7a0b
+#define PCI_DEVICE_ID_LOONGSON_7A1000_LPC	0x7a0c
+#define PCI_DEVICE_ID_LOONGSON_7A1000_DMA	0x7a0f
+#define PCI_DEVICE_ID_LOONGSON_7A1000_EHCI	0x7a14
+#define PCI_DEVICE_ID_LOONGSON_7A1000_GPU	0x7a15
+#define PCI_DEVICE_ID_LOONGSON_7A1000_PCIE_X4	0x7a19
+#define PCI_DEVICE_ID_LOONGSON_7A1000_OHCI	0x7a24
+#define PCI_DEVICE_ID_LOONGSON_7A1000_PCIE_X8	0x7a29
+
 #endif /* _LINUX_PCI_IDS_H */
-- 
2.1.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 2/6] AHCI: Add support for Loongson 7A1000 SATA controller
  2020-03-09  8:23 [PATCH 0/6] Add basic support for Loongson 7A1000 bridge chip Tiezhu Yang
  2020-03-09  8:23 ` [PATCH 1/6] PCI: Add Loongson vendor ID and 7A1000 device IDs Tiezhu Yang
@ 2020-03-09  8:23 ` Tiezhu Yang
  2020-03-09  8:23 ` [PATCH 3/6] MIPS: Loongson: Use firmware arguments to get board name Tiezhu Yang
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 21+ messages in thread
From: Tiezhu Yang @ 2020-03-09  8:23 UTC (permalink / raw)
  To: Thomas Bogendoerfer, Huacai Chen, Jiaxun Yang, Bjorn Helgaas, Jens Axboe
  Cc: linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li

Loongson 7A1000 SATA controller uses BAR0 as the base address register.

Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
 drivers/ata/ahci.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 11ea1af..28a336e 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -40,6 +40,7 @@
 enum {
 	AHCI_PCI_BAR_STA2X11	= 0,
 	AHCI_PCI_BAR_CAVIUM	= 0,
+	AHCI_PCI_BAR_LOONGSON	= 0,
 	AHCI_PCI_BAR_ENMOTUS	= 2,
 	AHCI_PCI_BAR_CAVIUM_GEN5	= 4,
 	AHCI_PCI_BAR_STANDARD	= 5,
@@ -589,6 +590,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
 	/* Enmotus */
 	{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },
 
+	/* Loongson */
+	{ PCI_VDEVICE(LOONGSON, PCI_DEVICE_ID_LOONGSON_7A1000_SATA),
+	  board_ahci },
+
 	/* Generic, PCI class code for AHCI */
 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
@@ -1680,6 +1685,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 			ahci_pci_bar = AHCI_PCI_BAR_CAVIUM;
 		if (pdev->device == 0xa084)
 			ahci_pci_bar = AHCI_PCI_BAR_CAVIUM_GEN5;
+	} else if (pdev->vendor == PCI_VENDOR_ID_LOONGSON) {
+		if (pdev->device == PCI_DEVICE_ID_LOONGSON_7A1000_SATA)
+			ahci_pci_bar = AHCI_PCI_BAR_LOONGSON;
 	}
 
 	/* acquire resources */
-- 
2.1.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 3/6] MIPS: Loongson: Use firmware arguments to get board name
  2020-03-09  8:23 [PATCH 0/6] Add basic support for Loongson 7A1000 bridge chip Tiezhu Yang
  2020-03-09  8:23 ` [PATCH 1/6] PCI: Add Loongson vendor ID and 7A1000 device IDs Tiezhu Yang
  2020-03-09  8:23 ` [PATCH 2/6] AHCI: Add support for Loongson 7A1000 SATA controller Tiezhu Yang
@ 2020-03-09  8:23 ` Tiezhu Yang
  2020-03-09  8:36   ` 回复:[PATCH " Jiaxun Yang
  2020-03-09  8:23 ` [PATCH 4/6] MIPS: Loongson: Add DMA support for 7A1000 Tiezhu Yang
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 21+ messages in thread
From: Tiezhu Yang @ 2020-03-09  8:23 UTC (permalink / raw)
  To: Thomas Bogendoerfer, Huacai Chen, Jiaxun Yang, Bjorn Helgaas, Jens Axboe
  Cc: linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li

In order to distinguish various types of bridge chip such as AMD RS780E
or Loongson 7A1000, we can use firmware arguments to get board name.

Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
 arch/mips/include/asm/mach-loongson64/boot_param.h | 1 +
 arch/mips/loongson64/env.c                         | 5 +++++
 2 files changed, 6 insertions(+)

diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h
index 8c286be..225a563 100644
--- a/arch/mips/include/asm/mach-loongson64/boot_param.h
+++ b/arch/mips/include/asm/mach-loongson64/boot_param.h
@@ -217,5 +217,6 @@ struct loongson_system_configuration {
 
 extern struct efi_memory_map_loongson *loongson_memmap;
 extern struct loongson_system_configuration loongson_sysconf;
+extern struct board_devices *eboard;
 
 #endif
diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c
index 0daeb7b..a244a8c 100644
--- a/arch/mips/loongson64/env.c
+++ b/arch/mips/loongson64/env.c
@@ -24,6 +24,9 @@ EXPORT_SYMBOL(cpu_clock_freq);
 struct efi_memory_map_loongson *loongson_memmap;
 struct loongson_system_configuration loongson_sysconf;
 
+struct board_devices *eboard;
+EXPORT_SYMBOL(eboard);
+
 u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
 u64 loongson_chiptemp[MAX_PACKAGES];
 u64 loongson_freqctrl[MAX_PACKAGES];
@@ -51,6 +54,8 @@ void __init prom_init_env(void)
 		((u64)loongson_p + loongson_p->system_offset);
 	ecpu = (struct efi_cpuinfo_loongson *)
 		((u64)loongson_p + loongson_p->cpu_offset);
+	eboard = (struct board_devices *)
+		((u64)loongson_p + loongson_p->boarddev_table_offset);
 	eirq_source = (struct irq_source_routing_table *)
 		((u64)loongson_p + loongson_p->irq_offset);
 	loongson_memmap = (struct efi_memory_map_loongson *)
-- 
2.1.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 4/6] MIPS: Loongson: Add DMA support for 7A1000
  2020-03-09  8:23 [PATCH 0/6] Add basic support for Loongson 7A1000 bridge chip Tiezhu Yang
                   ` (2 preceding siblings ...)
  2020-03-09  8:23 ` [PATCH 3/6] MIPS: Loongson: Use firmware arguments to get board name Tiezhu Yang
@ 2020-03-09  8:23 ` Tiezhu Yang
  2020-03-09  8:44   ` 回复:[PATCH " Jiaxun Yang
  2020-03-13  8:24   ` [PATCH " Christoph Hellwig
  2020-03-09  8:23 ` [PATCH 5/6] MIPS: Loongson: Add PCI " Tiezhu Yang
  2020-03-09  8:23 ` [PATCH 6/6] MIPS: Loongson: Add support for 7A1000 interrupt controller Tiezhu Yang
  5 siblings, 2 replies; 21+ messages in thread
From: Tiezhu Yang @ 2020-03-09  8:23 UTC (permalink / raw)
  To: Thomas Bogendoerfer, Huacai Chen, Jiaxun Yang, Bjorn Helgaas, Jens Axboe
  Cc: linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li

Implement __phys_to_dma() and __dma_to_phys() according to the
node id offset in 7A1000 DMA route config register.

Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
 arch/mips/include/asm/mach-loongson64/boot_param.h |  1 +
 arch/mips/loongson64/dma.c                         | 49 +++++++++++++++++++++-
 arch/mips/loongson64/init.c                        | 13 ++++++
 3 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h
index 225a563..60e7a7e 100644
--- a/arch/mips/include/asm/mach-loongson64/boot_param.h
+++ b/arch/mips/include/asm/mach-loongson64/boot_param.h
@@ -218,5 +218,6 @@ struct loongson_system_configuration {
 extern struct efi_memory_map_loongson *loongson_memmap;
 extern struct loongson_system_configuration loongson_sysconf;
 extern struct board_devices *eboard;
+extern u32 node_id_offset;
 
 #endif
diff --git a/arch/mips/loongson64/dma.c b/arch/mips/loongson64/dma.c
index 5e86635..997c257 100644
--- a/arch/mips/loongson64/dma.c
+++ b/arch/mips/loongson64/dma.c
@@ -2,24 +2,69 @@
 #include <linux/dma-direct.h>
 #include <linux/init.h>
 #include <linux/swiotlb.h>
+#include <boot_param.h>
 
-dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
+struct loongson_dma_ops {
+	dma_addr_t (*phys_to_dma)(struct device *dev, phys_addr_t paddr);
+	phys_addr_t (*dma_to_phys)(struct device *dev, dma_addr_t daddr);
+};
+
+struct loongson_dma_ops loongson_dma;
+
+dma_addr_t __rs780e_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);
 }
 
-phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr)
+dma_addr_t __ls7a_phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	long nid = (paddr >> 44) & 0x3;
+
+	return ((nid << 44) ^ paddr) | (nid << (36 + node_id_offset));
+}
+
+
+dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	return loongson_dma.phys_to_dma(dev, paddr);
+}
+
+phys_addr_t __rs780e_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);
 }
 
+phys_addr_t __ls7a_dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+	long nid = (daddr >> (36 + node_id_offset)) & 0x3;
+
+	return ((nid << (36 + node_id_offset)) ^ daddr) | (nid << 44);
+}
+
+phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+	return loongson_dma.dma_to_phys(dev, daddr);
+}
+
 void __init plat_swiotlb_setup(void)
 {
 	swiotlb_init(1);
+
+	if (strstr(eboard->name, "780E")) {
+		loongson_dma.phys_to_dma = __rs780e_phys_to_dma;
+		loongson_dma.dma_to_phys = __rs780e_dma_to_phys;
+	}
+
+	if (strstr(eboard->name, "7A1000")) {
+		loongson_dma.phys_to_dma = __ls7a_phys_to_dma;
+		loongson_dma.dma_to_phys = __ls7a_dma_to_phys;
+	}
 }
diff --git a/arch/mips/loongson64/init.c b/arch/mips/loongson64/init.c
index 5ac1a0f..dd8463d 100644
--- a/arch/mips/loongson64/init.c
+++ b/arch/mips/loongson64/init.c
@@ -12,6 +12,11 @@
 #include <asm/fw/fw.h>
 
 #include <loongson.h>
+#include <boot_param.h>
+
+#define NODE_ID_OFFSET_ADDR     0x90000E001001041CULL
+
+u32 node_id_offset;
 
 static void __init mips_nmi_setup(void)
 {
@@ -23,6 +28,11 @@ static void __init mips_nmi_setup(void)
 	flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
 }
 
+static void ls7a_early_config(void)
+{
+	node_id_offset = (*(u32 *)NODE_ID_OFFSET_ADDR >> 8) & 0x1F;
+}
+
 void __init prom_init(void)
 {
 	fw_init_cmdline();
@@ -32,6 +42,9 @@ void __init prom_init(void)
 	set_io_port_base((unsigned long)
 		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
 
+	if (strstr(eboard->name, "7A1000"))
+		ls7a_early_config();
+
 	prom_init_numa_memory();
 
 	/* Hardcode to CPU UART 0 */
-- 
2.1.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 5/6] MIPS: Loongson: Add PCI support for 7A1000
  2020-03-09  8:23 [PATCH 0/6] Add basic support for Loongson 7A1000 bridge chip Tiezhu Yang
                   ` (3 preceding siblings ...)
  2020-03-09  8:23 ` [PATCH 4/6] MIPS: Loongson: Add DMA support for 7A1000 Tiezhu Yang
@ 2020-03-09  8:23 ` Tiezhu Yang
  2020-03-09  8:47   ` 回复:[PATCH " Jiaxun Yang
  2020-03-09  8:23 ` [PATCH 6/6] MIPS: Loongson: Add support for 7A1000 interrupt controller Tiezhu Yang
  5 siblings, 1 reply; 21+ messages in thread
From: Tiezhu Yang @ 2020-03-09  8:23 UTC (permalink / raw)
  To: Thomas Bogendoerfer, Huacai Chen, Jiaxun Yang, Bjorn Helgaas, Jens Axboe
  Cc: linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li, Jianmin Lv

Add PCI support for 7A1000 to detect PCI device.

Co-developed-by: Jianmin Lv <lvjianmin@loongson.cn>
Signed-off-by: Jianmin Lv <lvjianmin@loongson.cn>
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
 arch/mips/include/asm/mach-loongson64/pci.h |   1 +
 arch/mips/loongson64/pci.c                  |  12 ++-
 arch/mips/pci/Makefile                      |   2 +-
 arch/mips/pci/ops-loongson3-ls7a.c          | 132 ++++++++++++++++++++++++++++
 4 files changed, 143 insertions(+), 4 deletions(-)
 create mode 100644 arch/mips/pci/ops-loongson3-ls7a.c

diff --git a/arch/mips/include/asm/mach-loongson64/pci.h b/arch/mips/include/asm/mach-loongson64/pci.h
index 8b59d64..42c9744 100644
--- a/arch/mips/include/asm/mach-loongson64/pci.h
+++ b/arch/mips/include/asm/mach-loongson64/pci.h
@@ -8,6 +8,7 @@
 #define __ASM_MACH_LOONGSON64_PCI_H_
 
 extern struct pci_ops loongson_pci_ops;
+extern struct pci_ops loongson_ls7a_pci_ops;
 
 /* this is an offset from mips_io_port_base */
 #define LOONGSON_PCI_IO_START	0x00004000UL
diff --git a/arch/mips/loongson64/pci.c b/arch/mips/loongson64/pci.c
index e84ae20..b79368f 100644
--- a/arch/mips/loongson64/pci.c
+++ b/arch/mips/loongson64/pci.c
@@ -23,8 +23,8 @@ static struct resource loongson_pci_io_resource = {
 	.flags	= IORESOURCE_IO,
 };
 
-static struct pci_controller  loongson_pci_controller = {
-	.pci_ops	= &loongson_pci_ops,
+static struct pci_controller loongson_pci_controller = {
+	.pci_ops	= NULL,
 	.io_resource	= &loongson_pci_io_resource,
 	.mem_resource	= &loongson_pci_mem_resource,
 	.mem_offset	= 0x00000000UL,
@@ -36,6 +36,11 @@ extern int sbx00_acpi_init(void);
 
 static int __init pcibios_init(void)
 {
+	if (strstr(eboard->name, "780E"))
+		loongson_pci_controller.pci_ops = &loongson_pci_ops;
+
+	if (strstr(eboard->name, "7A1000"))
+		loongson_pci_controller.pci_ops = &loongson_ls7a_pci_ops;
 
 	loongson_pci_controller.io_map_base = mips_io_port_base;
 	loongson_pci_mem_resource.start = loongson_sysconf.pci_mem_start_addr;
@@ -43,7 +48,8 @@ static int __init pcibios_init(void)
 
 	register_pci_controller(&loongson_pci_controller);
 
-	sbx00_acpi_init();
+	if (strstr(eboard->name, "780E"))
+		sbx00_acpi_init();
 
 	return 0;
 }
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 342ce10..7256bb1 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -35,7 +35,7 @@ obj-$(CONFIG_LASAT)		+= pci-lasat.o
 obj-$(CONFIG_MIPS_COBALT)	+= fixup-cobalt.o
 obj-$(CONFIG_LEMOTE_FULOONG2E)	+= fixup-fuloong2e.o ops-loongson2.o
 obj-$(CONFIG_LEMOTE_MACH2F)	+= fixup-lemote2f.o ops-loongson2.o
-obj-$(CONFIG_MACH_LOONGSON64)	+= fixup-loongson3.o ops-loongson3.o
+obj-$(CONFIG_MACH_LOONGSON64)	+= fixup-loongson3.o ops-loongson3.o ops-loongson3-ls7a.o
 obj-$(CONFIG_MIPS_MALTA)	+= fixup-malta.o pci-malta.o
 obj-$(CONFIG_PMC_MSP7120_GW)	+= fixup-pmcmsp.o ops-pmcmsp.o
 obj-$(CONFIG_PMC_MSP7120_EVAL)	+= fixup-pmcmsp.o ops-pmcmsp.o
diff --git a/arch/mips/pci/ops-loongson3-ls7a.c b/arch/mips/pci/ops-loongson3-ls7a.c
new file mode 100644
index 0000000..4ed6c40
--- /dev/null
+++ b/arch/mips/pci/ops-loongson3-ls7a.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Loongson Technology Corporation Limited
+ *
+ * Author: Jianmin Lv <lvjianmin@loongson.cn>
+ * Author: Tiezhu Yang <yangtiezhu@loongson.cn>
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+
+#include <asm/mips-boards/bonito64.h>
+
+#include <loongson.h>
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+#define HT1LO_PCICFG_BASE 0x1a000000
+#define HT1LO_PCICFG_BASE_TP1 0x1b000000
+
+#define HT1LO_PCICFG_BASE_EXT 0xefe00000000
+#define HT1LO_PCICFG_BASE_TP1_EXT 0xefe10000000
+
+static 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 (busnum == 0 &&
+		    reg == PCI_CLASS_REVISION && *data == 0x06000001)
+			*data = (PCI_CLASS_BRIDGE_PCI << 16) | (*data & 0xffff);
+
+		if (*data == 0xffffffff) {
+			*data = -1;
+			return PCIBIOS_DEVICE_NOT_FOUND;
+		}
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int ls7a_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+				 int where, int size, u32 *val)
+{
+	int ret;
+	u32 data = 0;
+
+	ret = ls7a_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		return ret;
+
+	if (size == 1)
+		*val = (data >> ((where & 3) << 3)) & 0xff;
+	else if (size == 2)
+		*val = (data >> ((where & 3) << 3)) & 0xffff;
+	else
+		*val = data;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int ls7a_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+				  int where, int size, u32 val)
+{
+	int ret;
+	u32 data = 0;
+
+	if (size == 4)
+		data = val;
+	else {
+		ret = ls7a_pci_config_access(PCI_ACCESS_READ, bus,
+						devfn, where, &data);
+		if (ret != PCIBIOS_SUCCESSFUL)
+			return ret;
+
+		if (size == 1)
+			data = (data & ~(0xff << ((where & 3) << 3))) |
+				(val << ((where & 3) << 3));
+		else if (size == 2)
+			data = (data & ~(0xffff << ((where & 3) << 3))) |
+				(val << ((where & 3) << 3));
+	}
+
+	ret = ls7a_pci_config_access(PCI_ACCESS_WRITE, bus,
+					devfn, where, &data);
+
+	return ret;
+}
+
+struct pci_ops loongson_ls7a_pci_ops = {
+	.read = ls7a_pci_pcibios_read,
+	.write = ls7a_pci_pcibios_write
+};
-- 
2.1.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 6/6] MIPS: Loongson: Add support for 7A1000 interrupt controller
  2020-03-09  8:23 [PATCH 0/6] Add basic support for Loongson 7A1000 bridge chip Tiezhu Yang
                   ` (4 preceding siblings ...)
  2020-03-09  8:23 ` [PATCH 5/6] MIPS: Loongson: Add PCI " Tiezhu Yang
@ 2020-03-09  8:23 ` Tiezhu Yang
  2020-03-09  9:07   ` 回复:[PATCH " Jiaxun Yang
  5 siblings, 1 reply; 21+ messages in thread
From: Tiezhu Yang @ 2020-03-09  8:23 UTC (permalink / raw)
  To: Thomas Bogendoerfer, Huacai Chen, Jiaxun Yang, Bjorn Helgaas, Jens Axboe
  Cc: linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li, Jianmin Lv

Use interrupt model to support interrupt controller of Loongson
7A1000 bridge chip.

Co-developed-by: Jianmin Lv <lvjianmin@loongson.cn>
Signed-off-by: Jianmin Lv <lvjianmin@loongson.cn>
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
 arch/mips/include/asm/mach-loongson64/ioaicu.h | 166 ++++++++++++++
 arch/mips/include/asm/mach-loongson64/irq.h    |   2 +
 arch/mips/loongson64/Makefile                  |   2 +-
 arch/mips/loongson64/ioaicu.c                  | 305 +++++++++++++++++++++++++
 arch/mips/loongson64/irq.c                     |  20 +-
 arch/mips/loongson64/smp.c                     |  11 +-
 6 files changed, 497 insertions(+), 9 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-loongson64/ioaicu.h
 create mode 100644 arch/mips/loongson64/ioaicu.c

diff --git a/arch/mips/include/asm/mach-loongson64/ioaicu.h b/arch/mips/include/asm/mach-loongson64/ioaicu.h
new file mode 100644
index 0000000..e55de0d
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson64/ioaicu.h
@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 Loongson Technology Corporation Limited
+ *
+ * Author: Jianmin Lv <lvjianmin@loongson.cn>
+ * Author: Tiezhu Yang <yangtiezhu@loongson.cn>
+ */
+
+#ifndef _ASM_LOONGSON_IOAICU_H
+#define _ASM_LOONGSON_IOAICU_H
+
+#define LS_CFG_BASE	0x3ff00000
+#define LS_CFG_OFF(x)	((void *)TO_UNCAC(LS_CFG_BASE) + (x))
+
+#define LS_IRC_BASE	LS_CFG_OFF(0x1400)
+#define LS_IRC_OFF(x)	(LS_IRC_BASE + x)
+
+#define LS_IRC_ENT(x)	LS_IRC_OFF(x)
+#define LS_IRC_EN	LS_IRC_OFF(0x24)
+#define LS_IRC_ENSET	LS_IRC_OFF(0x28)
+
+#define MAX_IOAICUS		16
+#define LS3A_MAX_IPI_IRQ	26
+#define LS3A_MAX_IO_VECTOR	64
+#define LS3A_MAX_IO_IRQ		256
+
+#define LS7A_PCH_REG_BASE	0x10000000
+#define LS7A_IOAICU_IRQ_BASE	64
+
+#define IOAICU_BASE	0x90000e0000000000ULL
+#define IOAICU_IMR	0x20
+#define IOAICU_IER	0x60
+#define IOAICU_ICR	0x80
+#define IOAICU_IRR	0x100
+#define IOAICU_ISR	0x3a0
+#define IOAICU_IPR	0x3e0
+
+#define USE_HTH_INT0	0x1
+
+#define LS3A_IOIRQ2VECTOR(irq) (irq - LS3A_MAX_IO_VECTOR)
+#define LS3A_VECTOR2IOIRQ(vector) (vector + LS3A_MAX_IO_VECTOR)
+
+struct ioaicu_config {
+	unsigned char aicuid;
+	unsigned char aicuver;
+	unsigned int aicuaddr;
+};
+
+struct ioaicu_gsi {
+	u32 gsi_base;
+	u32 gsi_end;
+};
+
+struct ioaicu {
+	int nr_registers;
+	struct ioaicu_config config;
+	struct ioaicu_gsi gsi_config;
+};
+
+struct loongson_irq_dispatch_ops {
+	void (*irq_dispatch)(void);
+};
+
+extern void setup_ioaicu(void);
+extern struct ioaicu ioaicus[MAX_IOAICUS];
+extern struct loongson_irq_dispatch_ops loongson_pch;
+extern unsigned short ls3a_ipi_pos2irq[LS3A_MAX_IO_VECTOR];
+
+extern void loongson3_send_irq_by_ipi(int cpu, int irqs);
+extern int plat_set_irq_affinity(struct irq_data *d,
+				 const struct cpumask *affinity, bool force);
+
+static inline unsigned long ioaicu_read64(unsigned int aicu, unsigned int reg)
+{
+	unsigned long addr = ioaicus[aicu].config.aicuaddr;
+
+	return *(unsigned long *)(IOAICU_BASE + addr + reg);
+}
+
+static inline void ioaicu_write64(unsigned int aicu,
+				  unsigned int reg, unsigned long value)
+{
+	unsigned long addr = ioaicus[aicu].config.aicuaddr;
+	*(unsigned long *)(IOAICU_BASE + addr + reg) = value;
+}
+
+static inline unsigned char ioaicu_read8(unsigned int aicu, unsigned int reg)
+{
+	unsigned long addr = ioaicus[aicu].config.aicuaddr;
+
+	return *(unsigned char *)(IOAICU_BASE + addr + reg);
+}
+
+static inline void ioaicu_write8(unsigned int aicu,
+				 unsigned int reg, unsigned char value)
+{
+	unsigned long addr = ioaicus[aicu].config.aicuaddr;
+	*(unsigned char *)(IOAICU_BASE + addr + reg) = value;
+}
+
+static inline int ioaicu_get_redir_entries(int ioaicu)
+{
+	return 64;
+}
+
+static inline struct ioaicu_gsi *ioaicu_gsi_routing(int ioaicu_idx)
+{
+	return &ioaicus[ioaicu_idx].gsi_config;
+}
+
+static inline int ioaicu_id(int ioaicu_idx)
+{
+	return ioaicus[ioaicu_idx].config.aicuid;
+}
+
+static inline unsigned int ioaicu_addr(int ioaicu_idx)
+{
+	return ioaicus[ioaicu_idx].config.aicuaddr;
+}
+
+#define ioaicu_ver(ioaicu_idx) ioaicus[ioaicu_idx].config.aicuver
+
+static inline void ls64_conf_write64(u64 val64, void __iomem *addr)
+{
+	asm volatile (
+	"	.set push\n"
+	"	.set noreorder\n"
+	"	sd	%[v], (%[hw])\n"
+	"	lb	$0, (%[hw])\n"
+	"	.set pop\n"
+	:
+	: [hw] "r" (addr),  [v] "r" (val64)
+	);
+}
+
+static inline void ls64_conf_write32(u32 val, void __iomem *addr)
+{
+	asm volatile (
+	"	.set push\n"
+	"	.set noreorder\n"
+	"	sw	%[v], (%[hw])\n"
+	"	lb	$0, (%[hw])\n"
+	"	.set pop\n"
+	:
+	: [hw] "r" (addr), [v] "r" (val)
+	);
+}
+
+static inline void ls64_conf_write8(u8 val, void __iomem *addr)
+{
+	asm volatile (
+	"	.set push\n"
+	"	.set noreorder\n"
+	"	sb	%[v], (%[hw])\n"
+	"	lb	$0, (%[hw])\n"
+	"	.set pop\n"
+	:
+	: [hw] "r" (addr), [v] "r" (val)
+	);
+}
+
+#define ls64_conf_read64(addr) readq(addr)
+#define ls64_conf_read32(addr) readl(addr)
+#define ls64_conf_read8(addr) readb(addr)
+
+#endif /* _ASM_LOONGSON_IOAICU_H */
diff --git a/arch/mips/include/asm/mach-loongson64/irq.h b/arch/mips/include/asm/mach-loongson64/irq.h
index 73a8991..10568be 100644
--- a/arch/mips/include/asm/mach-loongson64/irq.h
+++ b/arch/mips/include/asm/mach-loongson64/irq.h
@@ -4,6 +4,8 @@
 
 #include <boot_param.h>
 
+#define NR_IRQS (64 + 256)
+
 /* cpu core interrupt numbers */
 #define MIPS_CPU_IRQ_BASE 56
 
diff --git a/arch/mips/loongson64/Makefile b/arch/mips/loongson64/Makefile
index 7821891..3db50c6 100644
--- a/arch/mips/loongson64/Makefile
+++ b/arch/mips/loongson64/Makefile
@@ -3,7 +3,7 @@
 # Makefile for Loongson-3 family machines
 #
 obj-$(CONFIG_MACH_LOONGSON64) += irq.o cop2-ex.o platform.o acpi_init.o dma.o \
-				setup.o init.o env.o time.o reset.o \
+				setup.o init.o env.o time.o reset.o ioaicu.o \
 
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_NUMA)	+= numa.o
diff --git a/arch/mips/loongson64/ioaicu.c b/arch/mips/loongson64/ioaicu.c
new file mode 100644
index 0000000..904ac75
--- /dev/null
+++ b/arch/mips/loongson64/ioaicu.c
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Loongson Technology Corporation Limited
+ *
+ * Author: Jianmin Lv <lvjianmin@loongson.cn>
+ * Author: Tiezhu Yang <yangtiezhu@loongson.cn>
+ */
+
+#include <loongson.h>
+#include <ioaicu.h>
+
+static DEFINE_SPINLOCK(pch_irq_lock);
+DECLARE_BITMAP(ls3a_ipi_in_use, LS3A_MAX_IPI_IRQ);
+struct loongson_irq_dispatch_ops loongson_pch;
+struct ioaicu ioaicus[MAX_IOAICUS];
+
+unsigned short ls3a_ipi_pos2irq[LS3A_MAX_IO_VECTOR] = {
+					[0 ... LS3A_MAX_IO_VECTOR-1] = -1 };
+unsigned char ls3a_ipi_irq2pos[LS3A_MAX_IO_IRQ] = {
+					[0 ... LS3A_MAX_IO_IRQ-1] = -1 };
+unsigned int cpu_for_irq[LS3A_MAX_IO_IRQ] = {
+					[0 ... LS3A_MAX_IO_IRQ-1] = -1};
+
+u32 gsi_top;
+int nr_ioaicus;
+#define for_each_ioaicu(idx)	\
+	for ((idx) = 0; (idx) < nr_ioaicus; (idx)++)
+#define for_each_pin(idx, pin)	\
+	for ((pin) = 0; (pin) < ioaicus[(idx)].nr_registers; (pin)++)
+
+static int bad_ioaicu(unsigned long address)
+{
+	if (nr_ioaicus >= MAX_IOAICUS) {
+		pr_warn("WARNING: Max # of I/O AICUs (%d) exceeded (found %d), skipping\n",
+			MAX_IOAICUS, nr_ioaicus);
+		return 1;
+	}
+
+	if (!address) {
+		pr_warn("WARNING: Bogus (zero) I/O AICU address found in table, skipping!\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+static void register_ioaicu(int id, u32 address, u32 gsi_base)
+{
+	int idx = 0;
+	int entries;
+	struct ioaicu_gsi *gsi_cfg;
+
+	if (bad_ioaicu(address))
+		return;
+
+	idx = nr_ioaicus;
+	ioaicus[idx].config.aicuaddr = address;
+	ioaicus[idx].config.aicuid = id;
+	ioaicus[idx].config.aicuver = 0;
+
+	entries = ioaicu_get_redir_entries(idx);
+	gsi_cfg = ioaicu_gsi_routing(idx);
+	gsi_cfg->gsi_base = gsi_base;
+	gsi_cfg->gsi_end = gsi_base + entries - 1;
+
+	ioaicus[idx].nr_registers = entries;
+
+	if (gsi_cfg->gsi_end >= gsi_top)
+		gsi_top = gsi_cfg->gsi_end + 1;
+
+	pr_info("IOAICU[%d]: aicu_id %d, version %d, address 0x%x, GSI %d-%d\n",
+		idx, ioaicu_id(idx), ioaicu_ver(idx), ioaicu_addr(idx),
+		gsi_cfg->gsi_base, gsi_cfg->gsi_end);
+
+	nr_ioaicus++;
+}
+
+static int find_ioaicu(u32 gsi)
+{
+	int i;
+
+	if (nr_ioaicus == 0)
+		return -1;
+
+	for_each_ioaicu(i) {
+		struct ioaicu_gsi *gsi_cfg = ioaicu_gsi_routing(i);
+
+		if (gsi >= gsi_cfg->gsi_base && gsi <= gsi_cfg->gsi_end)
+			return i;
+	}
+
+	pr_err("ERROR: Unable to locate IOAICU for GSI %d\n", gsi);
+
+	return -1;
+}
+
+static int pch_create_dirq(unsigned int irq)
+{
+	unsigned long flags;
+	int pos;
+
+	spin_lock_irqsave(&pch_irq_lock, flags);
+again:
+	pos = find_first_zero_bit(ls3a_ipi_in_use, LS3A_MAX_IPI_IRQ);
+	if (pos == LS3A_MAX_IPI_IRQ) {
+		spin_unlock_irqrestore(&pch_irq_lock, flags);
+		return -ENOSPC;
+	}
+
+	if (test_and_set_bit(pos, ls3a_ipi_in_use))
+		goto again;
+
+	ls3a_ipi_pos2irq[pos] = irq;
+	ls3a_ipi_irq2pos[LS3A_IOIRQ2VECTOR(irq)] = pos;
+	spin_unlock_irqrestore(&pch_irq_lock, flags);
+
+	return 0;
+}
+
+static void pch_destroy_dirq(unsigned int irq)
+{
+	unsigned long flags;
+	int pos;
+
+	spin_lock_irqsave(&pch_irq_lock, flags);
+	pos = ls3a_ipi_irq2pos[LS3A_IOIRQ2VECTOR(irq)];
+	if (pos >= 0) {
+		clear_bit(pos, ls3a_ipi_in_use);
+		ls3a_ipi_irq2pos[LS3A_IOIRQ2VECTOR(irq)] = -1;
+		ls3a_ipi_pos2irq[pos] = -1;
+	}
+	spin_unlock_irqrestore(&pch_irq_lock, flags);
+}
+
+static void line_mask_pch_irq(struct irq_data *d)
+{
+	unsigned long flags, data;
+	unsigned int ioaicu;
+	unsigned long irq_nr = d->irq;
+
+	ioaicu = (unsigned int)find_ioaicu((u32)irq_nr);
+
+	spin_lock_irqsave(&pch_irq_lock, flags);
+	data = ioaicu_read64(ioaicu, IOAICU_IMR);
+	data |= (1ULL << LS3A_IOIRQ2VECTOR(irq_nr));
+	ioaicu_write64(ioaicu, IOAICU_IMR, data);
+	spin_unlock_irqrestore(&pch_irq_lock, flags);
+}
+
+static void line_unmask_pch_irq(struct irq_data *d)
+{
+	unsigned long flags, data;
+	unsigned int ioaicu;
+	unsigned long irq_nr = d->irq;
+
+	ioaicu = (unsigned int)find_ioaicu((u32)irq_nr);
+
+	spin_lock_irqsave(&pch_irq_lock, flags);
+	data = ioaicu_read64(ioaicu, IOAICU_IMR);
+	data &= ~(1ULL << LS3A_IOIRQ2VECTOR(irq_nr));
+	ioaicu_write64(ioaicu, IOAICU_IMR, data);
+	spin_unlock_irqrestore(&pch_irq_lock, flags);
+}
+
+static unsigned int line_startup_pch_irq(struct irq_data *d)
+{
+	pch_create_dirq(d->irq);
+	line_unmask_pch_irq(d);
+
+	return 0;
+}
+
+static void line_shutdown_pch_irq(struct irq_data *d)
+{
+	line_mask_pch_irq(d);
+	pch_destroy_dirq(d->irq);
+}
+
+static struct irq_chip ioaicu_line_chip = {
+	.name			= "IOAICU-LINE",
+	.irq_mask		= line_mask_pch_irq,
+	.irq_unmask		= line_unmask_pch_irq,
+	.irq_startup		= line_startup_pch_irq,
+	.irq_shutdown		= line_shutdown_pch_irq,
+	.irq_set_affinity	= plat_set_irq_affinity,
+};
+
+static void line_route_init(void)
+{
+	unsigned int dummy;
+
+	/* route 3A CPU0 INT0 to node0 core0 INT1(IP3) */
+	dummy = LOONGSON_INT_COREx_INTy(loongson_sysconf.boot_cpu_id, 1);
+	ls64_conf_write8(dummy, LS_IRC_ENT(0));
+
+	dummy = ls64_conf_read32(LS_IRC_EN);
+	dummy |= 0x1;
+	ls64_conf_write32(dummy, LS_IRC_ENSET);
+}
+
+static void init_pin_route(unsigned int ioaicu, int vec)
+{
+	ioaicu_write8(ioaicu, IOAICU_IRR + vec, USE_HTH_INT0);
+}
+
+static void init_ioaicu_pin(unsigned int ioaicu, int pin,
+			    struct irq_chip *pirq_chip)
+{
+	init_pin_route(ioaicu, LS3A_IOIRQ2VECTOR(pin));
+	irq_set_chip_and_handler(pin, pirq_chip, handle_level_irq);
+}
+
+static void setup_ioaicu_irqs(struct irq_chip *pirq_chip)
+{
+	unsigned int ioaicu, pin;
+	struct ioaicu_gsi *gsi_cfg;
+
+	for_each_ioaicu(ioaicu) {
+		ioaicu_write64(ioaicu, IOAICU_IER, 0);
+		ioaicu_write64(ioaicu, IOAICU_IPR, (1ULL << 59));
+		ioaicu_write64(ioaicu, IOAICU_ISR, 0);
+		ioaicu_write64(ioaicu, IOAICU_IMR, -1ULL);
+		ioaicu_write64(ioaicu, IOAICU_ICR, -1ULL);
+	}
+
+	for (ioaicu = 0; ioaicu < nr_ioaicus; ioaicu++) {
+		for (pin = 0; pin < ioaicus[ioaicu].nr_registers; pin++) {
+			gsi_cfg = ioaicu_gsi_routing(ioaicu);
+			init_ioaicu_pin(ioaicu,
+					pin + gsi_cfg->gsi_base, pirq_chip);
+		}
+	}
+}
+
+static void handle_irqs(unsigned long long irqs, int i)
+{
+	unsigned int irq;
+	struct irq_data *irqd;
+	struct cpumask affinity;
+	int cpu = smp_processor_id();
+
+	while (irqs) {
+		irq = __ffs(irqs);
+		irqs &= ~(1ULL<<irq);
+		irq += (i << 6);
+
+		/* handled by local core */
+		if (ls3a_ipi_irq2pos[irq] == (unsigned char)-1) {
+			do_IRQ(LS3A_VECTOR2IOIRQ(irq));
+			continue;
+		}
+
+		irqd = irq_get_irq_data(LS3A_VECTOR2IOIRQ(irq));
+		cpumask_and(&affinity, irqd->common->affinity, cpu_active_mask);
+		if (cpumask_empty(&affinity)) {
+			do_IRQ(LS3A_VECTOR2IOIRQ(irq));
+			continue;
+		}
+
+		cpu_for_irq[irq] = cpumask_next(cpu_for_irq[irq], &affinity);
+		if (cpu_for_irq[irq] >= nr_cpu_ids)
+			cpu_for_irq[irq] = cpumask_first(&affinity);
+
+		if (cpu_for_irq[irq] == cpu) {
+			do_IRQ(LS3A_VECTOR2IOIRQ(irq));
+			continue;
+		}
+
+		/* balanced by other cores */
+		loongson3_send_irq_by_ipi(cpu_for_irq[irq],
+					  (0x1 << (ls3a_ipi_irq2pos[irq])));
+	}
+}
+
+static void ioaicu_line_dispatch(void)
+{
+	unsigned long flags;
+	unsigned int ioaicu;
+	unsigned long long intstatus;
+	unsigned long long intmask;
+
+	for_each_ioaicu(ioaicu) {
+		/* read irq status register */
+		intstatus = ioaicu_read64(ioaicu, IOAICU_ISR);
+
+		spin_lock_irqsave(&pch_irq_lock, flags);
+		intmask = ioaicu_read64(ioaicu, IOAICU_IMR);
+		intmask |= intstatus;
+		ioaicu_write64(ioaicu, IOAICU_IMR, intmask);
+		intmask = ioaicu_read64(ioaicu, IOAICU_IMR);
+		spin_unlock_irqrestore(&pch_irq_lock, flags);
+
+		handle_irqs(intstatus, 0);
+	}
+}
+
+/* ioaicu: input/output advanced interrupt control unit */
+void __init setup_ioaicu(void)
+{
+	register_ioaicu(0, LS7A_PCH_REG_BASE, LS7A_IOAICU_IRQ_BASE);
+
+	line_route_init();
+	setup_ioaicu_irqs(&ioaicu_line_chip);
+	loongson_pch.irq_dispatch = ioaicu_line_dispatch;
+}
diff --git a/arch/mips/loongson64/irq.c b/arch/mips/loongson64/irq.c
index 79ad797..988f21f 100644
--- a/arch/mips/loongson64/irq.c
+++ b/arch/mips/loongson64/irq.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <loongson.h>
 #include <irq.h>
+#include <ioaicu.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 
@@ -71,6 +72,8 @@ static void ht_irqdispatch(void)
 			continue;
 		}
 
+		ls3a_ipi_pos2irq[ht_irq[i]] = ht_irq[i];
+
 		/* balanced by other cores */
 		loongson3_send_irq_by_ipi(irq_cpu[ht_irq[i]], (0x1 << ht_irq[i]));
 	}
@@ -91,7 +94,7 @@ asmlinkage void plat_irq_dispatch(void)
 		loongson3_ipi_interrupt(NULL);
 #endif
 	if (pending & CAUSEF_IP3)
-		ht_irqdispatch();
+		loongson_pch.irq_dispatch();
 	if (pending & CAUSEF_IP2)
 		do_IRQ(LOONGSON_UART_IRQ);
 	if (pending & UNUSED_IPS) {
@@ -137,11 +140,18 @@ void __init arch_init_irq(void)
 
 	clear_c0_status(ST0_IM | ST0_BEV);
 
-	irq_router_init();
 	mips_cpu_irq_init();
-	init_i8259_irqs();
-	chip = irq_get_chip(I8259A_IRQ_BASE);
-	chip->irq_set_affinity = plat_set_irq_affinity;
+
+	if (strstr(eboard->name, "780E")) {
+		irq_router_init();
+		init_i8259_irqs();
+		loongson_pch.irq_dispatch = ht_irqdispatch;
+		chip = irq_get_chip(I8259A_IRQ_BASE);
+		chip->irq_set_affinity = plat_set_irq_affinity;
+	}
+
+	if (strstr(eboard->name, "7A1000"))
+		setup_ioaicu();
 
 	irq_set_chip_and_handler(LOONGSON_UART_IRQ,
 			&loongson_irq_chip, handle_percpu_irq);
diff --git a/arch/mips/loongson64/smp.c b/arch/mips/loongson64/smp.c
index de8e074..0720df7 100644
--- a/arch/mips/loongson64/smp.c
+++ b/arch/mips/loongson64/smp.c
@@ -20,6 +20,7 @@
 #include <loongson.h>
 #include <loongson_regs.h>
 #include <workarounds.h>
+#include <ioaicu.h>
 
 #include "smp.h"
 
@@ -336,10 +337,14 @@ void loongson3_ipi_interrupt(struct pt_regs *regs)
 	}
 
 	if (irqs) {
-		int irq;
+		int irq, irq1;
+
 		while ((irq = ffs(irqs))) {
-			do_IRQ(irq-1);
-			irqs &= ~(1<<(irq-1));
+			irq1 = ls3a_ipi_pos2irq[irq - 1];
+			if (likely(irq1 != (unsigned short)-1)) {
+				do_IRQ(irq1);
+				irqs &= ~(1 << (irq - 1));
+			}
 		}
 	}
 }
-- 
2.1.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* 回复:[PATCH 3/6] MIPS: Loongson: Use firmware arguments to get board name
  2020-03-09  8:23 ` [PATCH 3/6] MIPS: Loongson: Use firmware arguments to get board name Tiezhu Yang
@ 2020-03-09  8:36   ` Jiaxun Yang
  2020-03-10  2:38     ` Tiezhu Yang
  0 siblings, 1 reply; 21+ messages in thread
From: Jiaxun Yang @ 2020-03-09  8:36 UTC (permalink / raw)
  To: Tiezhu Yang
  Cc: Thomas Bogendoerfer, Huacai Chen, Bjorn Helgaas, Jens Axboe,
	linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li



 ---- 在 星期一, 2020-03-09 16:23:23 Tiezhu Yang <yangtiezhu@loongson.cn> 撰写 ----
 > In order to distinguish various types of bridge chip such as AMD RS780E
 > or Loongson 7A1000, we can use firmware arguments to get board name.
 > 
Hi Tiezhu,

Thanks for your contribution.
Your series is sightly conflict with my "modernize" series. But that's fine,
if your code can meet mainline requirement, I'm going to adjust my works. 

See my comments bellow.

 > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
 > ---
 >  arch/mips/include/asm/mach-loongson64/boot_param.h | 1 +
 >  arch/mips/loongson64/env.c                         | 5 +++++
 >  2 files changed, 6 insertions(+)
 > 
 > diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h
 > index 8c286be..225a563 100644
 > --- a/arch/mips/include/asm/mach-loongson64/boot_param.h
 > +++ b/arch/mips/include/asm/mach-loongson64/boot_param.h
 > @@ -217,5 +217,6 @@ struct loongson_system_configuration {
 >  
 >  extern struct efi_memory_map_loongson *loongson_memmap;
 >  extern struct loongson_system_configuration loongson_sysconf;
 > +extern struct board_devices *eboard;
 >  
 >  #endif
 > diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c
 > index 0daeb7b..a244a8c 100644
 > --- a/arch/mips/loongson64/env.c
 > +++ b/arch/mips/loongson64/env.c
 > @@ -24,6 +24,9 @@ EXPORT_SYMBOL(cpu_clock_freq);
 >  struct efi_memory_map_loongson *loongson_memmap;
 >  struct loongson_system_configuration loongson_sysconf;
 >  
 > +struct board_devices *eboard;
 > +EXPORT_SYMBOL(eboard);

Can we make it as a part of struct loongson_sysconf and export that struct?
Memory of struct eboard is not managed by kernel,  we shouldn't export such symbol.

Also I noticed that you're checking PCH type repeatly in other subsystems. Can you just
determine the PCH type here?

 > +
 >  u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
 >  u64 loongson_chiptemp[MAX_PACKAGES];
 >  u64 loongson_freqctrl[MAX_PACKAGES];
 > @@ -51,6 +54,8 @@ void __init prom_init_env(void)
 >          ((u64)loongson_p + loongson_p->system_offset);
 >      ecpu = (struct efi_cpuinfo_loongson *)
 >          ((u64)loongson_p + loongson_p->cpu_offset);
 > +    eboard = (struct board_devices *)
 > +        ((u64)loongson_p + loongson_p->boarddev_table_offset);
 >      eirq_source = (struct irq_source_routing_table *)
 >          ((u64)loongson_p + loongson_p->irq_offset);
 >      loongson_memmap = (struct efi_memory_map_loongson *)
 > -- 
 > 2.1.0
 > 
 >

^ permalink raw reply	[flat|nested] 21+ messages in thread

* 回复:[PATCH 4/6] MIPS: Loongson: Add DMA support for 7A1000
  2020-03-09  8:23 ` [PATCH 4/6] MIPS: Loongson: Add DMA support for 7A1000 Tiezhu Yang
@ 2020-03-09  8:44   ` Jiaxun Yang
  2020-03-10  2:40     ` Tiezhu Yang
  2020-03-13  8:24   ` [PATCH " Christoph Hellwig
  1 sibling, 1 reply; 21+ messages in thread
From: Jiaxun Yang @ 2020-03-09  8:44 UTC (permalink / raw)
  To: Tiezhu Yang
  Cc: Thomas Bogendoerfer, Huacai Chen, Bjorn Helgaas, Jens Axboe,
	linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li



 ---- 在 星期一, 2020-03-09 16:23:24 Tiezhu Yang <yangtiezhu@loongson.cn> 撰写 ----
 > Implement __phys_to_dma() and __dma_to_phys() according to the
 > node id offset in 7A1000 DMA route config register.

That design shocked me a lot. And It is known that some firmware didn't configure
HT Recieve window correctly to make it work. So probably for mainline kernel,
just set DMA_MASK to limit LS7A DMA address to Node0 would be a better Option?
 
 > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
 > ---
 >  arch/mips/include/asm/mach-loongson64/boot_param.h |  1 +
 >  arch/mips/loongson64/dma.c                         | 49 +++++++++++++++++++++-
 >  arch/mips/loongson64/init.c                        | 13 ++++++
 >  3 files changed, 61 insertions(+), 2 deletions(-)
 > 
 > diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h
 > index 225a563..60e7a7e 100644
 > --- a/arch/mips/include/asm/mach-loongson64/boot_param.h
 > +++ b/arch/mips/include/asm/mach-loongson64/boot_param.h
 > @@ -218,5 +218,6 @@ struct loongson_system_configuration {
 >  extern struct efi_memory_map_loongson *loongson_memmap;
 >  extern struct loongson_system_configuration loongson_sysconf;
 >  extern struct board_devices *eboard;
 > +extern u32 node_id_offset;
 >  
 >  #endif
 > diff --git a/arch/mips/loongson64/dma.c b/arch/mips/loongson64/dma.c
 > index 5e86635..997c257 100644
 > --- a/arch/mips/loongson64/dma.c
 > +++ b/arch/mips/loongson64/dma.c
 > @@ -2,24 +2,69 @@
 >  #include <linux/dma-direct.h>
 >  #include <linux/init.h>
 >  #include <linux/swiotlb.h>
 > +#include <boot_param.h>
 >  
 > -dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
 > +struct loongson_dma_ops {
 > +    dma_addr_t (*phys_to_dma)(struct device *dev, phys_addr_t paddr);
 > +    phys_addr_t (*dma_to_phys)(struct device *dev, dma_addr_t daddr);
 > +};
 > +
 > +struct loongson_dma_ops loongson_dma;
 > +
 > +dma_addr_t __rs780e_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);
 >  }
 >  
 > -phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr)
 > +dma_addr_t __ls7a_phys_to_dma(struct device *dev, phys_addr_t paddr)
 > +{
 > +    long nid = (paddr >> 44) & 0x3;
 > +
 > +    return ((nid << 44) ^ paddr) | (nid << (36 + node_id_offset));
 > +}
 > +
 > +
 > +dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
 > +{
 > +    return loongson_dma.phys_to_dma(dev, paddr);
 > +}
 > +
 > +phys_addr_t __rs780e_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);
 >  }
 >  
 > +phys_addr_t __ls7a_dma_to_phys(struct device *dev, dma_addr_t daddr)
 > +{
 > +    long nid = (daddr >> (36 + node_id_offset)) & 0x3;
 > +
 > +    return ((nid << (36 + node_id_offset)) ^ daddr) | (nid << 44);
 > +}
 > +
 > +phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr)
 > +{
 > +    return loongson_dma.dma_to_phys(dev, daddr);
 > +}
 > +
 >  void __init plat_swiotlb_setup(void)
 >  {
 >      swiotlb_init(1);
 > +
 > +    if (strstr(eboard->name, "780E")) {
 > +        loongson_dma.phys_to_dma = __rs780e_phys_to_dma;
 > +        loongson_dma.dma_to_phys = __rs780e_dma_to_phys;
 > +    }
 > +
 > +    if (strstr(eboard->name, "7A1000")) {
 > +        loongson_dma.phys_to_dma = __ls7a_phys_to_dma;
 > +        loongson_dma.dma_to_phys = __ls7a_dma_to_phys;
 > +    }
 >  }
 > diff --git a/arch/mips/loongson64/init.c b/arch/mips/loongson64/init.c
 > index 5ac1a0f..dd8463d 100644
 > --- a/arch/mips/loongson64/init.c
 > +++ b/arch/mips/loongson64/init.c
 > @@ -12,6 +12,11 @@
 >  #include <asm/fw/fw.h>
 >  
 >  #include <loongson.h>
 > +#include <boot_param.h>
 > +
 > +#define NODE_ID_OFFSET_ADDR     0x90000E001001041CULL
 > +
 > +u32 node_id_offset;
 >  
 >  static void __init mips_nmi_setup(void)
 >  {
 > @@ -23,6 +28,11 @@ static void __init mips_nmi_setup(void)
 >      flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
 >  }
 >  
 > +static void ls7a_early_config(void)
 > +{
 > +    node_id_offset = (*(u32 *)NODE_ID_OFFSET_ADDR >> 8) & 0x1F;

Please avoid raw pointer. Use readl/writel instead.

 > +}
 > +
 >  void __init prom_init(void)
 >  {
 >      fw_init_cmdline();
 > @@ -32,6 +42,9 @@ void __init prom_init(void)
 >      set_io_port_base((unsigned long)
 >          ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
 >  
 > +    if (strstr(eboard->name, "7A1000"))
 > +        ls7a_early_config();
 > +
 >      prom_init_numa_memory();
 >  
 >      /* Hardcode to CPU UART 0 */
 > -- 
 > 2.1.0
 > 
 >

^ permalink raw reply	[flat|nested] 21+ messages in thread

* 回复:[PATCH 5/6] MIPS: Loongson: Add PCI support for 7A1000
  2020-03-09  8:23 ` [PATCH 5/6] MIPS: Loongson: Add PCI " Tiezhu Yang
@ 2020-03-09  8:47   ` Jiaxun Yang
  2020-03-10  3:03     ` Tiezhu Yang
  0 siblings, 1 reply; 21+ messages in thread
From: Jiaxun Yang @ 2020-03-09  8:47 UTC (permalink / raw)
  To: Tiezhu Yang
  Cc: Thomas Bogendoerfer, Huacai Chen, Bjorn Helgaas, Jens Axboe,
	linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li,
	Jianmin Lv



 ---- 在 星期一, 2020-03-09 16:23:25 Tiezhu Yang <yangtiezhu@loongson.cn> 撰写 ----
 > Add PCI support for 7A1000 to detect PCI device.
 > 
 > Co-developed-by: Jianmin Lv <lvjianmin@loongson.cn>
 > Signed-off-by: Jianmin Lv <lvjianmin@loongson.cn>
 > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
 > ---
 >  arch/mips/include/asm/mach-loongson64/pci.h |   1 +
 >  arch/mips/loongson64/pci.c                  |  12 ++-
 >  arch/mips/pci/Makefile                      |   2 +-
 >  arch/mips/pci/ops-loongson3-ls7a.c          | 132 ++++++++++++++++++++++++++++
 >  4 files changed, 143 insertions(+), 4 deletions(-)
 >  create mode 100644 arch/mips/pci/ops-loongson3-ls7a.c
 > 
 > diff --git a/arch/mips/include/asm/mach-loongson64/pci.h b/arch/mips/include/asm/mach-loongson64/pci.h
 > index 8b59d64..42c9744 100644
 > --- a/arch/mips/include/asm/mach-loongson64/pci.h
 > +++ b/arch/mips/include/asm/mach-loongson64/pci.h
 > @@ -8,6 +8,7 @@
 >  #define __ASM_MACH_LOONGSON64_PCI_H_
 >  
 >  extern struct pci_ops loongson_pci_ops;
 > +extern struct pci_ops loongson_ls7a_pci_ops;
 >  
 >  /* this is an offset from mips_io_port_base */
 >  #define LOONGSON_PCI_IO_START    0x00004000UL
 > diff --git a/arch/mips/loongson64/pci.c b/arch/mips/loongson64/pci.c
 > index e84ae20..b79368f 100644
 > --- a/arch/mips/loongson64/pci.c
 > +++ b/arch/mips/loongson64/pci.c
 > @@ -23,8 +23,8 @@ static struct resource loongson_pci_io_resource = {
 >      .flags    = IORESOURCE_IO,
 >  };
 >  
 > -static struct pci_controller  loongson_pci_controller = {
 > -    .pci_ops    = &loongson_pci_ops,
 > +static struct pci_controller loongson_pci_controller = {
 > +    .pci_ops    = NULL,
 >      .io_resource    = &loongson_pci_io_resource,
 >      .mem_resource    = &loongson_pci_mem_resource,
 >      .mem_offset    = 0x00000000UL,
 > @@ -36,6 +36,11 @@ extern int sbx00_acpi_init(void);
 >  
 >  static int __init pcibios_init(void)
 >  {
 > +    if (strstr(eboard->name, "780E"))
 > +        loongson_pci_controller.pci_ops = &loongson_pci_ops;
 > +
 > +    if (strstr(eboard->name, "7A1000"))
 > +        loongson_pci_controller.pci_ops = &loongson_ls7a_pci_ops;

Please do not check PCH type everywhere.

 >  
 >      loongson_pci_controller.io_map_base = mips_io_port_base;
 >      loongson_pci_mem_resource.start = loongson_sysconf.pci_mem_start_addr;
 > @@ -43,7 +48,8 @@ static int __init pcibios_init(void)
 >  
 >      register_pci_controller(&loongson_pci_controller);
 >  
 > -    sbx00_acpi_init();
 > +    if (strstr(eboard->name, "780E"))
 > +        sbx00_acpi_init();
 >  
 >      return 0;
 >  }
 > diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
 > index 342ce10..7256bb1 100644
 > --- a/arch/mips/pci/Makefile
 > +++ b/arch/mips/pci/Makefile
 > @@ -35,7 +35,7 @@ obj-$(CONFIG_LASAT)        += pci-lasat.o
 >  obj-$(CONFIG_MIPS_COBALT)    += fixup-cobalt.o
 >  obj-$(CONFIG_LEMOTE_FULOONG2E)    += fixup-fuloong2e.o ops-loongson2.o
 >  obj-$(CONFIG_LEMOTE_MACH2F)    += fixup-lemote2f.o ops-loongson2.o
 > -obj-$(CONFIG_MACH_LOONGSON64)    += fixup-loongson3.o ops-loongson3.o
 > +obj-$(CONFIG_MACH_LOONGSON64)    += fixup-loongson3.o ops-loongson3.o ops-loongson3-ls7a.o
 >  obj-$(CONFIG_MIPS_MALTA)    += fixup-malta.o pci-malta.o
 >  obj-$(CONFIG_PMC_MSP7120_GW)    += fixup-pmcmsp.o ops-pmcmsp.o
 >  obj-$(CONFIG_PMC_MSP7120_EVAL)    += fixup-pmcmsp.o ops-pmcmsp.o
 > diff --git a/arch/mips/pci/ops-loongson3-ls7a.c b/arch/mips/pci/ops-loongson3-ls7a.c
 > new file mode 100644
 > index 0000000..4ed6c40
 > --- /dev/null
 > +++ b/arch/mips/pci/ops-loongson3-ls7a.c
 > @@ -0,0 +1,132 @@
 > +// SPDX-License-Identifier: GPL-2.0
 > +/*
 > + * Copyright (C) 2020 Loongson Technology Corporation Limited
 > + *
 > + * Author: Jianmin Lv <lvjianmin@loongson.cn>
 > + * Author: Tiezhu Yang <yangtiezhu@loongson.cn>
 > + */
 > +
 > +#include <linux/types.h>
 > +#include <linux/pci.h>
 > +#include <linux/kernel.h>
 > +
 > +#include <asm/mips-boards/bonito64.h>

Why we need this?

 > +
 > +#include <loongson.h>
 > +
 > +#define PCI_ACCESS_READ 0
 > +#define PCI_ACCESS_WRITE 1
 > +
 > +#define HT1LO_PCICFG_BASE 0x1a000000
 > +#define HT1LO_PCICFG_BASE_TP1 0x1b000000
 > +
 > +#define HT1LO_PCICFG_BASE_EXT 0xefe00000000
 > +#define HT1LO_PCICFG_BASE_TP1_EXT 0xefe10000000
 > +
 > +static 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 (busnum == 0 &&
 > +            reg == PCI_CLASS_REVISION && *data == 0x06000001)
 > +            *data = (PCI_CLASS_BRIDGE_PCI << 16) | (*data & 0xffff);

It should be a part of quirk. Not a part of accessing.

 > +
 > +        if (*data == 0xffffffff) {
 > +            *data = -1;
 > +            return PCIBIOS_DEVICE_NOT_FOUND;
 > +        }
 > +    }
 > +
 > +    return PCIBIOS_SUCCESSFUL;
 > +}
 > +
 > +static int ls7a_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn,
 > +                 int where, int size, u32 *val)
 > +{
 > +    int ret;
 > +    u32 data = 0;
 > +
 > +    ret = ls7a_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
 > +    if (ret != PCIBIOS_SUCCESSFUL)
 > +        return ret;
 > +
 > +    if (size == 1)
 > +        *val = (data >> ((where & 3) << 3)) & 0xff;
 > +    else if (size == 2)
 > +        *val = (data >> ((where & 3) << 3)) & 0xffff;
 > +    else
 > +        *val = data;

That  loggic seems identical with RS780E one, can we reuse them?

> +
 > +    return PCIBIOS_SUCCESSFUL;
 > +}
 > +
 > +static int ls7a_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn,
 > +                  int where, int size, u32 val)
 > +{
 > +    int ret;
 > +    u32 data = 0;
 > +
 > +    if (size == 4)
 > +        data = val;
 > +    else {
 > +        ret = ls7a_pci_config_access(PCI_ACCESS_READ, bus,
 > +                        devfn, where, &data);
 > +        if (ret != PCIBIOS_SUCCESSFUL)
 > +            return ret;
 > +
 > +        if (size == 1)
 > +            data = (data & ~(0xff << ((where & 3) << 3))) |
 > +                (val << ((where & 3) << 3));
 > +        else if (size == 2)
 > +            data = (data & ~(0xffff << ((where & 3) << 3))) |
 > +                (val << ((where & 3) << 3));
 > +    }
 > +
 > +    ret = ls7a_pci_config_access(PCI_ACCESS_WRITE, bus,
 > +                    devfn, where, &data);
 > +
 > +    return ret;
 > +}
 > +
 > +struct pci_ops loongson_ls7a_pci_ops = {
 > +    .read = ls7a_pci_pcibios_read,
 > +    .write = ls7a_pci_pcibios_write
 > +};
 > -- 
 > 2.1.0
 > 
 >

^ permalink raw reply	[flat|nested] 21+ messages in thread

* 回复:[PATCH 1/6] PCI: Add Loongson vendor ID and 7A1000 device IDs
  2020-03-09  8:23 ` [PATCH 1/6] PCI: Add Loongson vendor ID and 7A1000 device IDs Tiezhu Yang
@ 2020-03-09  8:50   ` Jiaxun Yang
  2020-03-10  2:31     ` Tiezhu Yang
  0 siblings, 1 reply; 21+ messages in thread
From: Jiaxun Yang @ 2020-03-09  8:50 UTC (permalink / raw)
  To: Tiezhu Yang
  Cc: Thomas Bogendoerfer, Huacai Chen, Bjorn Helgaas, Jens Axboe,
	linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li


 ---- 在 星期一, 2020-03-09 16:23:21 Tiezhu Yang <yangtiezhu@loongson.cn> 撰写 ----
 > Add the Loongson vendor ID and 7A1000 device IDs to pci_ids.h
 > to be used by the controller driver in the future.
 > 
 > The Loongson IDs can be found at the following link:
 > https://git.kernel.org/pub/scm/utils/pciutils/pciutils.git/tree/pci.ids
 > 
 > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
 > ---
 >  include/linux/pci_ids.h | 18 ++++++++++++++++++
 >  1 file changed, 18 insertions(+)
 > 
 > diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
 > index 352c0d7..0125ab4 100644
 > --- a/include/linux/pci_ids.h
 > +++ b/include/linux/pci_ids.h
 > @@ -3113,4 +3113,22 @@
 >  
 >  #define PCI_VENDOR_ID_NCUBE        0x10ff
 >  
 > +#define PCI_VENDOR_ID_LOONGSON            0x0014
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_HT    0x7a00
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_APB    0x7a02
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_GMAC    0x7a03
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_OTG    0x7a04
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_DC    0x7a06
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_HDA    0x7a07
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_SATA    0x7a08
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_PCIE_X1    0x7a09
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_SPI    0x7a0b
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_LPC    0x7a0c
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_DMA    0x7a0f
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_EHCI    0x7a14
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_GPU    0x7a15
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_PCIE_X4    0x7a19
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_OHCI    0x7a24
 > +#define PCI_DEVICE_ID_LOONGSON_7A1000_PCIE_X8    0x7a29

Devices IDs are unlikely to be reused by mutiple subsystems, so probably we don't need
to add them here?
 
> +
 >  #endif /* _LINUX_PCI_IDS_H */
 > -- 
 > 2.1.0
 > 
 >

^ permalink raw reply	[flat|nested] 21+ messages in thread

* 回复:[PATCH 6/6] MIPS: Loongson: Add support for 7A1000 interrupt controller
  2020-03-09  8:23 ` [PATCH 6/6] MIPS: Loongson: Add support for 7A1000 interrupt controller Tiezhu Yang
@ 2020-03-09  9:07   ` Jiaxun Yang
  2020-03-10  4:28     ` Tiezhu Yang
  0 siblings, 1 reply; 21+ messages in thread
From: Jiaxun Yang @ 2020-03-09  9:07 UTC (permalink / raw)
  To: Tiezhu Yang
  Cc: Thomas Bogendoerfer, Huacai Chen, Bjorn Helgaas, Jens Axboe,
	linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li,
	Jianmin Lv


 ---- 在 星期一, 2020-03-09 16:23:26 Tiezhu Yang <yangtiezhu@loongson.cn> 撰写 ----
 > Use interrupt model to support interrupt controller of Loongson
 > 7A1000 bridge chip.

This patch seems clueless for me.
Partly beacuse you're hijacking what should be done by irq domain and irqchip.
Variuous of abbreviations makes me frustrated, so I didn't dig in to your logic deeper. 
See my review comments below.

 > 
 > Co-developed-by: Jianmin Lv <lvjianmin@loongson.cn>
 > Signed-off-by: Jianmin Lv <lvjianmin@loongson.cn>
 > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
 > ---
 >  arch/mips/include/asm/mach-loongson64/ioaicu.h | 166 ++++++++++++++
 >  arch/mips/include/asm/mach-loongson64/irq.h    |   2 +
 >  arch/mips/loongson64/Makefile                  |   2 +-
 >  arch/mips/loongson64/ioaicu.c                  | 305 +++++++++++++++++++++++++
 >  arch/mips/loongson64/irq.c                     |  20 +-
 >  arch/mips/loongson64/smp.c                     |  11 +-
 >  6 files changed, 497 insertions(+), 9 deletions(-)
 >  create mode 100644 arch/mips/include/asm/mach-loongson64/ioaicu.h
 >  create mode 100644 arch/mips/loongson64/ioaicu.c
 > 
 > diff --git a/arch/mips/include/asm/mach-loongson64/ioaicu.h b/arch/mips/include/asm/mach-loongson64/ioaicu.h
 > new file mode 100644
 > index 0000000..e55de0d
 > --- /dev/null
 > +++ b/arch/mips/include/asm/mach-loongson64/ioaicu.h
 > @@ -0,0 +1,166 @@
 > +/* SPDX-License-Identifier: GPL-2.0 */
 > +/*
 > + * Copyright (C) 2020 Loongson Technology Corporation Limited
 > + *
 > + * Author: Jianmin Lv <lvjianmin@loongson.cn>
 > + * Author: Tiezhu Yang <yangtiezhu@loongson.cn>
 > + */
 > +
 > +#ifndef _ASM_LOONGSON_IOAICU_H
 > +#define _ASM_LOONGSON_IOAICU_H
 > +
 > +#define LS_CFG_BASE    0x3ff00000

Here your "_BASE" is using phys addr.

 > +#define LS_CFG_OFF(x)    ((void *)TO_UNCAC(LS_CFG_BASE) + (x))
 > +
 > +#define LS_IRC_BASE    LS_CFG_OFF(0x1400)
 > +#define LS_IRC_OFF(x)    (LS_IRC_BASE + x)
 > +
 > +#define LS_IRC_ENT(x)    LS_IRC_OFF(x)
 > +#define LS_IRC_EN    LS_IRC_OFF(0x24)
 > +#define LS_IRC_ENSET    LS_IRC_OFF(0x28)
 > +
 > +#define MAX_IOAICUS        16
 > +#define LS3A_MAX_IPI_IRQ    26
 > +#define LS3A_MAX_IO_VECTOR    64
 > +#define LS3A_MAX_IO_IRQ        256
 > +
 > +#define LS7A_PCH_REG_BASE    0x10000000
 > +#define LS7A_IOAICU_IRQ_BASE    64
 > +
 > +#define IOAICU_BASE    0x90000e0000000000ULL

But here your "_BASE" is using virt addr.

 > +#define IOAICU_IMR    0x20
 > +#define IOAICU_IER    0x60
 > +#define IOAICU_ICR    0x80
 > +#define IOAICU_IRR    0x100
 > +#define IOAICU_ISR    0x3a0
 > +#define IOAICU_IPR    0x3e0
 > +
 > +#define USE_HTH_INT0    0x1

What's that?

 > +
 > +#define LS3A_IOIRQ2VECTOR(irq) (irq - LS3A_MAX_IO_VECTOR)
 > +#define LS3A_VECTOR2IOIRQ(vector) (vector + LS3A_MAX_IO_VECTOR)
 > +
 > +struct ioaicu_config {
 > +    unsigned char aicuid;
 > +    unsigned char aicuver;
 > +    unsigned int aicuaddr;
 > +};
 > +
 > +struct ioaicu_gsi {
 > +    u32 gsi_base;
 > +    u32 gsi_end;
 > +};

What's meant by GSI?

 > +
 > +struct ioaicu {
 > +    int nr_registers;
 > +    struct ioaicu_config config;
 > +    struct ioaicu_gsi gsi_config;
 > +};
 > +
 > +struct loongson_irq_dispatch_ops {
 > +    void (*irq_dispatch)(void);
 > +};
 > +
 > +extern void setup_ioaicu(void);
 > +extern struct ioaicu ioaicus[MAX_IOAICUS];
 > +extern struct loongson_irq_dispatch_ops loongson_pch;
 > +extern unsigned short ls3a_ipi_pos2irq[LS3A_MAX_IO_VECTOR];
 > +
 > +extern void loongson3_send_irq_by_ipi(int cpu, int irqs);
 > +extern int plat_set_irq_affinity(struct irq_data *d,
 > +                 const struct cpumask *affinity, bool force);
 > +
 > +static inline unsigned long ioaicu_read64(unsigned int aicu, unsigned int reg)
 > +{
 > +    unsigned long addr = ioaicus[aicu].config.aicuaddr;
 > +
 > +    return *(unsigned long *)(IOAICU_BASE + addr + reg);

Please avoid raw pointer. Also applied to rest of the patch. 

 > +}
 > +
 > +static inline void ioaicu_write64(unsigned int aicu,
 > +                  unsigned int reg, unsigned long value)
 > +{
 > +    unsigned long addr = ioaicus[aicu].config.aicuaddr;
 > +    *(unsigned long *)(IOAICU_BASE + addr + reg) = value; 
> +}
 > +
 > +static inline unsigned char ioaicu_read8(unsigned int aicu, unsigned int reg)
 > +{
 > +    unsigned long addr = ioaicus[aicu].config.aicuaddr;
 > +
 > +    return *(unsigned char *)(IOAICU_BASE + addr + reg);
 > +}
 > +
 > +static inline void ioaicu_write8(unsigned int aicu,
 > +                 unsigned int reg, unsigned char value)
 > +{
 > +    unsigned long addr = ioaicus[aicu].config.aicuaddr;
 > +    *(unsigned char *)(IOAICU_BASE + addr + reg) = value;
 > +}
 > +
 > +static inline int ioaicu_get_redir_entries(int ioaicu)
 > +{
 > +    return 64;

Why not a macro?

 > +}
 > +
 > +static inline struct ioaicu_gsi *ioaicu_gsi_routing(int ioaicu_idx)
 > +{
 > +    return &ioaicus[ioaicu_idx].gsi_config;
 > +}
 > +
 > +static inline int ioaicu_id(int ioaicu_idx)
 > +{
 > +    return ioaicus[ioaicu_idx].config.aicuid;
 > +}
 > +
 > +static inline unsigned int ioaicu_addr(int ioaicu_idx)
 > +{
 > +    return ioaicus[ioaicu_idx].config.aicuaddr;
 > +}
 > +
 > +#define ioaicu_ver(ioaicu_idx) ioaicus[ioaicu_idx].config.aicuver
 > +
 > +static inline void ls64_conf_write64(u64 val64, void __iomem *addr)
 > +{
 > +    asm volatile (
 > +    "    .set push\n"
 > +    "    .set noreorder\n"
 > +    "    sd    %[v], (%[hw])\n"
 > +    "    lb    $0, (%[hw])\n"
 > +    "    .set pop\n"
 > +    :
 > +    : [hw] "r" (addr),  [v] "r" (val64)
 > +    );
 > +}

What are you doing here? I assume you're trying to workaround hardware bug?
Is it an io barrier? If so, please make it as a part of general io.h.

 > +
 > +static inline void ls64_conf_write32(u32 val, void __iomem *addr)
 > +{
 > +    asm volatile (
 > +    "    .set push\n"
 > +    "    .set noreorder\n"
 > +    "    sw    %[v], (%[hw])\n"
 > +    "    lb    $0, (%[hw])\n"
 > +    "    .set pop\n"
 > +    :
 > +    : [hw] "r" (addr), [v] "r" (val)
 > +    );
 > +}
 > +
 > +static inline void ls64_conf_write8(u8 val, void __iomem *addr)
 > +{
 > +    asm volatile (
 > +    "    .set push\n"
 > +    "    .set noreorder\n"
 > +    "    sb    %[v], (%[hw])\n"
 > +    "    lb    $0, (%[hw])\n"
 > +    "    .set pop\n"
 > +    :
 > +    : [hw] "r" (addr), [v] "r" (val)
 > +    );
 > +}
 > +
 > +#define ls64_conf_read64(addr) readq(addr)
 > +#define ls64_conf_read32(addr) readl(addr)
 > +#define ls64_conf_read8(addr) readb(addr)
 > +
 > +#endif /* _ASM_LOONGSON_IOAICU_H */
 > diff --git a/arch/mips/include/asm/mach-loongson64/irq.h b/arch/mips/include/asm/mach-loongson64/irq.h
 > index 73a8991..10568be 100644
 > --- a/arch/mips/include/asm/mach-loongson64/irq.h
 > +++ b/arch/mips/include/asm/mach-loongson64/irq.h
 > @@ -4,6 +4,8 @@
 >  
 >  #include <boot_param.h>
 >  
 > +#define NR_IRQS (64 + 256)
 > +
 >  /* cpu core interrupt numbers */
 >  #define MIPS_CPU_IRQ_BASE 56
 >  
 > diff --git a/arch/mips/loongson64/Makefile b/arch/mips/loongson64/Makefile
 > index 7821891..3db50c6 100644
 > --- a/arch/mips/loongson64/Makefile
 > +++ b/arch/mips/loongson64/Makefile
 > @@ -3,7 +3,7 @@
 >  # Makefile for Loongson-3 family machines
 >  #
 >  obj-$(CONFIG_MACH_LOONGSON64) += irq.o cop2-ex.o platform.o acpi_init.o dma.o \
 > -                setup.o init.o env.o time.o reset.o \
 > +                setup.o init.o env.o time.o reset.o ioaicu.o \
 >  
 >  obj-$(CONFIG_SMP)    += smp.o
 >  obj-$(CONFIG_NUMA)    += numa.o
 > diff --git a/arch/mips/loongson64/ioaicu.c b/arch/mips/loongson64/ioaicu.c
 > new file mode 100644
 > index 0000000..904ac75
 > --- /dev/null
 > +++ b/arch/mips/loongson64/ioaicu.c
 > @@ -0,0 +1,305 @@
 > +// SPDX-License-Identifier: GPL-2.0
 > +/*
 > + * Copyright (C) 2020 Loongson Technology Corporation Limited
 > + *
 > + * Author: Jianmin Lv <lvjianmin@loongson.cn>
 > + * Author: Tiezhu Yang <yangtiezhu@loongson.cn>
 > + */
 > +
 > +#include <loongson.h>
 > +#include <ioaicu.h>
 > +
 > +static DEFINE_SPINLOCK(pch_irq_lock);
 > +DECLARE_BITMAP(ls3a_ipi_in_use, LS3A_MAX_IPI_IRQ);
 > +struct loongson_irq_dispatch_ops loongson_pch;
 > +struct ioaicu ioaicus[MAX_IOAICUS];
 > +
 > +unsigned short ls3a_ipi_pos2irq[LS3A_MAX_IO_VECTOR] = {
 > +                    [0 ... LS3A_MAX_IO_VECTOR-1] = -1 };
 > +unsigned char ls3a_ipi_irq2pos[LS3A_MAX_IO_IRQ] = {
 > +                    [0 ... LS3A_MAX_IO_IRQ-1] = -1 };
 > +unsigned int cpu_for_irq[LS3A_MAX_IO_IRQ] = {
 > +                    [0 ... LS3A_MAX_IO_IRQ-1] = -1};
 > +
 > +u32 gsi_top;
 > +int nr_ioaicus;
 > +#define for_each_ioaicu(idx)    \
 > +    for ((idx) = 0; (idx) < nr_ioaicus; (idx)++)
 > +#define for_each_pin(idx, pin)    \
 > +    for ((pin) = 0; (pin) < ioaicus[(idx)].nr_registers; (pin)++)
 > +
 > +static int bad_ioaicu(unsigned long address)
 > +{
 > +    if (nr_ioaicus >= MAX_IOAICUS) {
 > +        pr_warn("WARNING: Max # of I/O AICUs (%d) exceeded (found %d), skipping\n",
 > +            MAX_IOAICUS, nr_ioaicus);
 > +        return 1;
 > +    }
 > +
 > +    if (!address) {
 > +        pr_warn("WARNING: Bogus (zero) I/O AICU address found in table, skipping!\n");
 > +        return 1;
 > +    }
 > +
 > +    return 0;
 > +}
 > +
 > +static void register_ioaicu(int id, u32 address, u32 gsi_base)
 > +{
 > +    int idx = 0;
 > +    int entries;
 > +    struct ioaicu_gsi *gsi_cfg;
 > +
 > +    if (bad_ioaicu(address))
 > +        return;
 > +
 > +    idx = nr_ioaicus;
 > +    ioaicus[idx].config.aicuaddr = address;
 > +    ioaicus[idx].config.aicuid = id;
 > +    ioaicus[idx].config.aicuver = 0;
 > +
 > +    entries = ioaicu_get_redir_entries(idx);
 > +    gsi_cfg = ioaicu_gsi_routing(idx);
 > +    gsi_cfg->gsi_base = gsi_base;
 > +    gsi_cfg->gsi_end = gsi_base + entries - 1;
 > +
 > +    ioaicus[idx].nr_registers = entries;
 > +
 > +    if (gsi_cfg->gsi_end >= gsi_top)
 > +        gsi_top = gsi_cfg->gsi_end + 1;
 > +
 > +    pr_info("IOAICU[%d]: aicu_id %d, version %d, address 0x%x, GSI %d-%d\n",
 > +        idx, ioaicu_id(idx), ioaicu_ver(idx), ioaicu_addr(idx),
 > +        gsi_cfg->gsi_base, gsi_cfg->gsi_end);
 > +
 > +    nr_ioaicus++;
 > +}
 > +
 > +static int find_ioaicu(u32 gsi)
 > +{
 > +    int i;
 > +
 > +    if (nr_ioaicus == 0)
 > +        return -1;
 > +
 > +    for_each_ioaicu(i) {
 > +        struct ioaicu_gsi *gsi_cfg = ioaicu_gsi_routing(i);
 > +
 > +        if (gsi >= gsi_cfg->gsi_base && gsi <= gsi_cfg->gsi_end)
 > +            return i;
 > +    }
 > +
 > +    pr_err("ERROR: Unable to locate IOAICU for GSI %d\n", gsi);
 > +
 > +    return -1;
 > +}
 > +
 > +static int pch_create_dirq(unsigned int irq)
 > +{
 > +    unsigned long flags;
 > +    int pos;
 > +
 > +    spin_lock_irqsave(&pch_irq_lock, flags);
 > +again:
 > +    pos = find_first_zero_bit(ls3a_ipi_in_use, LS3A_MAX_IPI_IRQ);
 > +    if (pos == LS3A_MAX_IPI_IRQ) {
 > +        spin_unlock_irqrestore(&pch_irq_lock, flags);
 > +        return -ENOSPC;
 > +    }

See Hierarchy IRQ domain, that's what you need.


 > +
 > +    if (test_and_set_bit(pos, ls3a_ipi_in_use))
 > +        goto again;
 > +
 > +    ls3a_ipi_pos2irq[pos] = irq;
 > +    ls3a_ipi_irq2pos[LS3A_IOIRQ2VECTOR(irq)] = pos;
 > +    spin_unlock_irqrestore(&pch_irq_lock, flags);
 > +
 > +    return 0;
 > +}
 > +
 > +static void pch_destroy_dirq(unsigned int irq)
 > +{
 > +    unsigned long flags;
 > +    int pos;
 > +
 > +    spin_lock_irqsave(&pch_irq_lock, flags);
 > +    pos = ls3a_ipi_irq2pos[LS3A_IOIRQ2VECTOR(irq)];
 > +    if (pos >= 0) {
 > +        clear_bit(pos, ls3a_ipi_in_use);
 > +        ls3a_ipi_irq2pos[LS3A_IOIRQ2VECTOR(irq)] = -1;
 > +        ls3a_ipi_pos2irq[pos] = -1;
 > +    }
 > +    spin_unlock_irqrestore(&pch_irq_lock, flags);
 > +}
 > +
 > +static void line_mask_pch_irq(struct irq_data *d)
 > +{
 > +    unsigned long flags, data;
 > +    unsigned int ioaicu;
 > +    unsigned long irq_nr = d->irq;
 > +
 > +    ioaicu = (unsigned int)find_ioaicu((u32)irq_nr);
 > +
 > +    spin_lock_irqsave(&pch_irq_lock, flags);
 > +    data = ioaicu_read64(ioaicu, IOAICU_IMR);
 > +    data |= (1ULL << LS3A_IOIRQ2VECTOR(irq_nr));
 > +    ioaicu_write64(ioaicu, IOAICU_IMR, data);
 > +    spin_unlock_irqrestore(&pch_irq_lock, flags);
 > +}
 > +
 > +static void line_unmask_pch_irq(struct irq_data *d)
 > +{
 > +    unsigned long flags, data;
 > +    unsigned int ioaicu;
 > +    unsigned long irq_nr = d->irq;
 > +
 > +    ioaicu = (unsigned int)find_ioaicu((u32)irq_nr);
 > +
 > +    spin_lock_irqsave(&pch_irq_lock, flags);
 > +    data = ioaicu_read64(ioaicu, IOAICU_IMR);
 > +    data &= ~(1ULL << LS3A_IOIRQ2VECTOR(irq_nr));
 > +    ioaicu_write64(ioaicu, IOAICU_IMR, data);
 > +    spin_unlock_irqrestore(&pch_irq_lock, flags);
 > +}
 > +
 > +static unsigned int line_startup_pch_irq(struct irq_data *d)
 > +{
 > +    pch_create_dirq(d->irq);
 > +    line_unmask_pch_irq(d);
 > +
 > +    return 0;
 > +}
 > +
 > +static void line_shutdown_pch_irq(struct irq_data *d)
 > +{
 > +    line_mask_pch_irq(d);
 > +    pch_destroy_dirq(d->irq);
 > +}
 > +
 > +static struct irq_chip ioaicu_line_chip = {
 > +    .name            = "IOAICU-LINE",
 > +    .irq_mask        = line_mask_pch_irq,
 > +    .irq_unmask        = line_unmask_pch_irq,
 > +    .irq_startup        = line_startup_pch_irq,
 > +    .irq_shutdown        = line_shutdown_pch_irq,
 > +    .irq_set_affinity    = plat_set_irq_affinity,
 > +};
 > +
 > +static void line_route_init(void)
 > +{
 > +    unsigned int dummy;
 > +
 > +    /* route 3A CPU0 INT0 to node0 core0 INT1(IP3) */
 > +    dummy = LOONGSON_INT_COREx_INTy(loongson_sysconf.boot_cpu_id, 1);
 > +    ls64_conf_write8(dummy, LS_IRC_ENT(0));
 > +
 > +    dummy = ls64_conf_read32(LS_IRC_EN);
 > +    dummy |= 0x1;
 > +    ls64_conf_write32(dummy, LS_IRC_ENSET);
 > +}
 > +
 > +static void init_pin_route(unsigned int ioaicu, int vec)
 > +{
 > +    ioaicu_write8(ioaicu, IOAICU_IRR + vec, USE_HTH_INT0);
 > +}
 > +
 > +static void init_ioaicu_pin(unsigned int ioaicu, int pin,
 > +                struct irq_chip *pirq_chip)
 > +{
 > +    init_pin_route(ioaicu, LS3A_IOIRQ2VECTOR(pin));
 > +    irq_set_chip_and_handler(pin, pirq_chip, handle_level_irq);
 > +}
 > +
 > +static void setup_ioaicu_irqs(struct irq_chip *pirq_chip)
 > +{
 > +    unsigned int ioaicu, pin;
 > +    struct ioaicu_gsi *gsi_cfg;
 > +
 > +    for_each_ioaicu(ioaicu) {
 > +        ioaicu_write64(ioaicu, IOAICU_IER, 0);
 > +        ioaicu_write64(ioaicu, IOAICU_IPR, (1ULL << 59));
 > +        ioaicu_write64(ioaicu, IOAICU_ISR, 0);
 > +        ioaicu_write64(ioaicu, IOAICU_IMR, -1ULL);
 > +        ioaicu_write64(ioaicu, IOAICU_ICR, -1ULL);
 > +    }
 > +
 > +    for (ioaicu = 0; ioaicu < nr_ioaicus; ioaicu++) {
 > +        for (pin = 0; pin < ioaicus[ioaicu].nr_registers; pin++) {
 > +            gsi_cfg = ioaicu_gsi_routing(ioaicu);
 > +            init_ioaicu_pin(ioaicu,
 > +                    pin + gsi_cfg->gsi_base, pirq_chip);
 > +        }
 > +    }
 > +}
 > +
 > +static void handle_irqs(unsigned long long irqs, int i)
 > +{
 > +    unsigned int irq;
 > +    struct irq_data *irqd;
 > +    struct cpumask affinity;
 > +    int cpu = smp_processor_id();
 > +
 > +    while (irqs) {
 > +        irq = __ffs(irqs);
 > +        irqs &= ~(1ULL<<irq);
 > +        irq += (i << 6);
 > +
 > +        /* handled by local core */
 > +        if (ls3a_ipi_irq2pos[irq] == (unsigned char)-1) {
 > +            do_IRQ(LS3A_VECTOR2IOIRQ(irq));
 > +            continue;
 > +        }
 > +
 > +        irqd = irq_get_irq_data(LS3A_VECTOR2IOIRQ(irq));
 > +        cpumask_and(&affinity, irqd->common->affinity, cpu_active_mask);
 > +        if (cpumask_empty(&affinity)) {
 > +            do_IRQ(LS3A_VECTOR2IOIRQ(irq));
 > +            continue;
 > +        }
 > +
 > +        cpu_for_irq[irq] = cpumask_next(cpu_for_irq[irq], &affinity);
 > +        if (cpu_for_irq[irq] >= nr_cpu_ids)
 > +            cpu_for_irq[irq] = cpumask_first(&affinity);
 > +
 > +        if (cpu_for_irq[irq] == cpu) {
 > +            do_IRQ(LS3A_VECTOR2IOIRQ(irq));
 > +            continue;
 > +        }
 > +
 > +        /* balanced by other cores */
 > +        loongson3_send_irq_by_ipi(cpu_for_irq[irq],
 > +                      (0x1 << (ls3a_ipi_irq2pos[irq])));
 > +    }
 > +}
 > +
 > +static void ioaicu_line_dispatch(void)
 > +{
 > +    unsigned long flags;
 > +    unsigned int ioaicu;
 > +    unsigned long long intstatus;
 > +    unsigned long long intmask;
 > +
 > +    for_each_ioaicu(ioaicu) {
 > +        /* read irq status register */
 > +        intstatus = ioaicu_read64(ioaicu, IOAICU_ISR);
 > +
 > +        spin_lock_irqsave(&pch_irq_lock, flags);
 > +        intmask = ioaicu_read64(ioaicu, IOAICU_IMR);
 > +        intmask |= intstatus;
 > +        ioaicu_write64(ioaicu, IOAICU_IMR, intmask);
 > +        intmask = ioaicu_read64(ioaicu, IOAICU_IMR);
 > +        spin_unlock_irqrestore(&pch_irq_lock, flags);
 > +
 > +        handle_irqs(intstatus, 0);
 > +    }
 > +}
 > +
 > +/* ioaicu: input/output advanced interrupt control unit */
 > +void __init setup_ioaicu(void)
 > +{
 > +    register_ioaicu(0, LS7A_PCH_REG_BASE, LS7A_IOAICU_IRQ_BASE);
 > +
 > +    line_route_init();
 > +    setup_ioaicu_irqs(&ioaicu_line_chip);
 > +    loongson_pch.irq_dispatch = ioaicu_line_dispatch;
 > +}
 > diff --git a/arch/mips/loongson64/irq.c b/arch/mips/loongson64/irq.c
 > index 79ad797..988f21f 100644
 > --- a/arch/mips/loongson64/irq.c
 > +++ b/arch/mips/loongson64/irq.c
 > @@ -1,6 +1,7 @@
 >  // SPDX-License-Identifier: GPL-2.0
 >  #include <loongson.h>
 >  #include <irq.h>
 > +#include <ioaicu.h>
 >  #include <linux/interrupt.h>
 >  #include <linux/init.h>
 >  
 > @@ -71,6 +72,8 @@ static void ht_irqdispatch(void)
 >              continue;
 >          }
 >  
 > +        ls3a_ipi_pos2irq[ht_irq[i]] = ht_irq[i];
 > +
 >          /* balanced by other cores */
 >          loongson3_send_irq_by_ipi(irq_cpu[ht_irq[i]], (0x1 << ht_irq[i]));
 >      }
 > @@ -91,7 +94,7 @@ asmlinkage void plat_irq_dispatch(void)
 >          loongson3_ipi_interrupt(NULL);
 >  #endif
 >      if (pending & CAUSEF_IP3)
 > -        ht_irqdispatch();
 > +        loongson_pch.irq_dispatch();
 >      if (pending & CAUSEF_IP2)
 >          do_IRQ(LOONGSON_UART_IRQ);
 >      if (pending & UNUSED_IPS) {
 > @@ -137,11 +140,18 @@ void __init arch_init_irq(void)
 >  
 >      clear_c0_status(ST0_IM | ST0_BEV);
 >  
 > -    irq_router_init();
 >      mips_cpu_irq_init();
 > -    init_i8259_irqs();
 > -    chip = irq_get_chip(I8259A_IRQ_BASE);
 > -    chip->irq_set_affinity = plat_set_irq_affinity;
 > +
 > +    if (strstr(eboard->name, "780E")) {
 > +        irq_router_init();
 > +        init_i8259_irqs();
 > +        loongson_pch.irq_dispatch = ht_irqdispatch;
 > +        chip = irq_get_chip(I8259A_IRQ_BASE);
 > +        chip->irq_set_affinity = plat_set_irq_affinity;
 > +    }
 > +
 > +    if (strstr(eboard->name, "7A1000"))
 > +        setup_ioaicu();

Ahh... strstr again.
Forgot to mention, you'd better make RS780E as fallback when no PCH type string
found in eboard name. That's to Loongson's crappy specification, 2/5 of my Loongson
boards didn't set their board name correctly.

 >  
 >      irq_set_chip_and_handler(LOONGSON_UART_IRQ,
 >              &loongson_irq_chip, handle_percpu_irq);
 > diff --git a/arch/mips/loongson64/smp.c b/arch/mips/loongson64/smp.c
 > index de8e074..0720df7 100644
 > --- a/arch/mips/loongson64/smp.c
 > +++ b/arch/mips/loongson64/smp.c
 > @@ -20,6 +20,7 @@
 >  #include <loongson.h>
 >  #include <loongson_regs.h>
 >  #include <workarounds.h>
 > +#include <ioaicu.h>
 >  
 >  #include "smp.h"
 >  
 > @@ -336,10 +337,14 @@ void loongson3_ipi_interrupt(struct pt_regs *regs)
 >      }
 >  
 >      if (irqs) {
 > -        int irq;
 > +        int irq, irq1;
 > +
 >          while ((irq = ffs(irqs))) {
 > -            do_IRQ(irq-1);
 > -            irqs &= ~(1<<(irq-1));
 > +            irq1 = ls3a_ipi_pos2irq[irq - 1];
 > +            if (likely(irq1 != (unsigned short)-1)) {
 > +                do_IRQ(irq1);
 > +                irqs &= ~(1 << (irq - 1));
 > +            }
 >          }
 >      }
 >  }
 > -- 
 > 2.1.0
 > 
 >

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: 回复:[PATCH 1/6] PCI: Add Loongson vendor ID and 7A1000 device IDs
  2020-03-09  8:50   ` 回复:[PATCH " Jiaxun Yang
@ 2020-03-10  2:31     ` Tiezhu Yang
  2020-03-10  2:37       ` Jiaxun Yang
  0 siblings, 1 reply; 21+ messages in thread
From: Tiezhu Yang @ 2020-03-10  2:31 UTC (permalink / raw)
  To: Jiaxun Yang
  Cc: Thomas Bogendoerfer, Huacai Chen, Bjorn Helgaas, Jens Axboe,
	linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li

On 03/09/2020 04:50 PM, Jiaxun Yang wrote:
>   ---- 在 星期一, 2020-03-09 16:23:21 Tiezhu Yang <yangtiezhu@loongson.cn> 撰写 ----
>   > Add the Loongson vendor ID and 7A1000 device IDs to pci_ids.h
>   > to be used by the controller driver in the future.
>   >
>   > The Loongson IDs can be found at the following link:
>   > https://git.kernel.org/pub/scm/utils/pciutils/pciutils.git/tree/pci.ids
>   >
>   > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
>   > ---
>   >  include/linux/pci_ids.h | 18 ++++++++++++++++++
>   >  1 file changed, 18 insertions(+)
>   >
>   > diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
>   > index 352c0d7..0125ab4 100644
>   > --- a/include/linux/pci_ids.h
>   > +++ b/include/linux/pci_ids.h
>   > @@ -3113,4 +3113,22 @@
>   >
>   >  #define PCI_VENDOR_ID_NCUBE        0x10ff
>   >
>   > +#define PCI_VENDOR_ID_LOONGSON            0x0014
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_HT    0x7a00
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_APB    0x7a02
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_GMAC    0x7a03
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_OTG    0x7a04
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_DC    0x7a06
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_HDA    0x7a07
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_SATA    0x7a08
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_PCIE_X1    0x7a09
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_SPI    0x7a0b
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_LPC    0x7a0c
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_DMA    0x7a0f
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_EHCI    0x7a14
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_GPU    0x7a15
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_PCIE_X4    0x7a19
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_OHCI    0x7a24
>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_PCIE_X8    0x7a29
>
> Devices IDs are unlikely to be reused by mutiple subsystems, so probably we don't need
> to add them here?

Hi Jiaxun,

I think it is better to define the device IDs in pci_ids.h,
otherwise it seems a little disorganized.

Thanks,

Tiezhu Yang

>   
>> +
>   >  #endif /* _LINUX_PCI_IDS_H */
>   > --
>   > 2.1.0
>   >
>   >


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: 回复:[PATCH 1/6] PCI: Add Loongson vendor ID and 7A1000 device IDs
  2020-03-10  2:31     ` Tiezhu Yang
@ 2020-03-10  2:37       ` Jiaxun Yang
  2020-03-10  9:28         ` Tiezhu Yang
  0 siblings, 1 reply; 21+ messages in thread
From: Jiaxun Yang @ 2020-03-10  2:37 UTC (permalink / raw)
  To: Tiezhu Yang
  Cc: Thomas Bogendoerfer, Huacai Chen, Bjorn Helgaas, Jens Axboe,
	linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li



于 2020年3月10日 GMT+08:00 上午10:31:56, Tiezhu Yang <yangtiezhu@loongson.cn> 写到:
>On 03/09/2020 04:50 PM, Jiaxun Yang wrote:
>>   ---- 在 星期一, 2020-03-09 16:23:21 Tiezhu Yang
><yangtiezhu@loongson.cn> 撰写 ----
>>   > Add the Loongson vendor ID and 7A1000 device IDs to pci_ids.h
>>   > to be used by the controller driver in the future.
>>   >
>>   > The Loongson IDs can be found at the following link:
>>   >
>https://git.kernel.org/pub/scm/utils/pciutils/pciutils.git/tree/pci.ids
>>   >
>>   > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
>>   > ---
>>   >  include/linux/pci_ids.h | 18 ++++++++++++++++++
>>   >  1 file changed, 18 insertions(+)
>>   >
>>   > diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
>>   > index 352c0d7..0125ab4 100644
>>   > --- a/include/linux/pci_ids.h
>>   > +++ b/include/linux/pci_ids.h
>>   > @@ -3113,4 +3113,22 @@
>>   >
>>   >  #define PCI_VENDOR_ID_NCUBE        0x10ff
>>   >
>>   > +#define PCI_VENDOR_ID_LOONGSON            0x0014
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_HT    0x7a00
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_APB    0x7a02
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_GMAC    0x7a03
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_OTG    0x7a04
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_DC    0x7a06
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_HDA    0x7a07
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_SATA    0x7a08
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_PCIE_X1    0x7a09
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_SPI    0x7a0b
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_LPC    0x7a0c
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_DMA    0x7a0f
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_EHCI    0x7a14
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_GPU    0x7a15
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_PCIE_X4    0x7a19
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_OHCI    0x7a24
>>   > +#define PCI_DEVICE_ID_LOONGSON_7A1000_PCIE_X8    0x7a29
>>
>> Devices IDs are unlikely to be reused by mutiple subsystems, so
>probably we don't need
>> to add them here?
>
>Hi Jiaxun,
>
>I think it is better to define the device IDs in pci_ids.h,
>otherwise it seems a little disorganized.

Please read the comment at the start of this file.
New entries should be added only if they're shared by multiple drivers.

That's the rule.

And probably you can split these two patches into a new series
as they're likely to be accepted.

Thanks.

>
>Thanks,
>
>Tiezhu Yang
>
>>   
>>> +
>>   >  #endif /* _LINUX_PCI_IDS_H */
>>   > --
>>   > 2.1.0
>>   >
>>   >

-- 
Jiaxun Yang

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: 回复:[PATCH 3/6] MIPS: Loongson: Use firmware arguments to get board name
  2020-03-09  8:36   ` 回复:[PATCH " Jiaxun Yang
@ 2020-03-10  2:38     ` Tiezhu Yang
  0 siblings, 0 replies; 21+ messages in thread
From: Tiezhu Yang @ 2020-03-10  2:38 UTC (permalink / raw)
  To: Jiaxun Yang
  Cc: Thomas Bogendoerfer, Huacai Chen, Bjorn Helgaas, Jens Axboe,
	linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li

On 03/09/2020 04:36 PM, Jiaxun Yang wrote:
>
>   ---- 在 星期一, 2020-03-09 16:23:23 Tiezhu Yang <yangtiezhu@loongson.cn> 撰写 ----
>   > In order to distinguish various types of bridge chip such as AMD RS780E
>   > or Loongson 7A1000, we can use firmware arguments to get board name.
>   >
> Hi Tiezhu,
>
> Thanks for your contribution.
> Your series is sightly conflict with my "modernize" series. But that's fine,
> if your code can meet mainline requirement, I'm going to adjust my works.

Hi Jiaxun,

Thanks very much for your kindly reply.

>
> See my comments bellow.
>
>   > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
>   > ---
>   >  arch/mips/include/asm/mach-loongson64/boot_param.h | 1 +
>   >  arch/mips/loongson64/env.c                         | 5 +++++
>   >  2 files changed, 6 insertions(+)
>   >
>   > diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h
>   > index 8c286be..225a563 100644
>   > --- a/arch/mips/include/asm/mach-loongson64/boot_param.h
>   > +++ b/arch/mips/include/asm/mach-loongson64/boot_param.h
>   > @@ -217,5 +217,6 @@ struct loongson_system_configuration {
>   >
>   >  extern struct efi_memory_map_loongson *loongson_memmap;
>   >  extern struct loongson_system_configuration loongson_sysconf;
>   > +extern struct board_devices *eboard;
>   >
>   >  #endif
>   > diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c
>   > index 0daeb7b..a244a8c 100644
>   > --- a/arch/mips/loongson64/env.c
>   > +++ b/arch/mips/loongson64/env.c
>   > @@ -24,6 +24,9 @@ EXPORT_SYMBOL(cpu_clock_freq);
>   >  struct efi_memory_map_loongson *loongson_memmap;
>   >  struct loongson_system_configuration loongson_sysconf;
>   >
>   > +struct board_devices *eboard;
>   > +EXPORT_SYMBOL(eboard);
>
> Can we make it as a part of struct loongson_sysconf and export that struct?
> Memory of struct eboard is not managed by kernel,  we shouldn't export such symbol.

OK, I will do it.

>
> Also I noticed that you're checking PCH type repeatly in other subsystems. Can you just
> determine the PCH type here?

Yes, of course.

Thanks,

Tiezhu Yang

>
>   > +
>   >  u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
>   >  u64 loongson_chiptemp[MAX_PACKAGES];
>   >  u64 loongson_freqctrl[MAX_PACKAGES];
>   > @@ -51,6 +54,8 @@ void __init prom_init_env(void)
>   >          ((u64)loongson_p + loongson_p->system_offset);
>   >      ecpu = (struct efi_cpuinfo_loongson *)
>   >          ((u64)loongson_p + loongson_p->cpu_offset);
>   > +    eboard = (struct board_devices *)
>   > +        ((u64)loongson_p + loongson_p->boarddev_table_offset);
>   >      eirq_source = (struct irq_source_routing_table *)
>   >          ((u64)loongson_p + loongson_p->irq_offset);
>   >      loongson_memmap = (struct efi_memory_map_loongson *)
>   > --
>   > 2.1.0
>   >
>   >


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: 回复:[PATCH 4/6] MIPS: Loongson: Add DMA support for 7A1000
  2020-03-09  8:44   ` 回复:[PATCH " Jiaxun Yang
@ 2020-03-10  2:40     ` Tiezhu Yang
  0 siblings, 0 replies; 21+ messages in thread
From: Tiezhu Yang @ 2020-03-10  2:40 UTC (permalink / raw)
  To: Jiaxun Yang
  Cc: Thomas Bogendoerfer, Huacai Chen, Bjorn Helgaas, Jens Axboe,
	linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li

On 03/09/2020 04:44 PM, Jiaxun Yang wrote:
>
>   ---- 在 星期一, 2020-03-09 16:23:24 Tiezhu Yang <yangtiezhu@loongson.cn> 撰写 ----
>   > Implement __phys_to_dma() and __dma_to_phys() according to the
>   > node id offset in 7A1000 DMA route config register.
>
> That design shocked me a lot. And It is known that some firmware didn't configure
> HT Recieve window correctly to make it work. So probably for mainline kernel,
> just set DMA_MASK to limit LS7A DMA address to Node0 would be a better Option?

Hi Jiaxun,

Let me rethink it and find a proper way.

>   
>   > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
>   > ---
>   >  arch/mips/include/asm/mach-loongson64/boot_param.h |  1 +
>   >  arch/mips/loongson64/dma.c                         | 49 +++++++++++++++++++++-
>   >  arch/mips/loongson64/init.c                        | 13 ++++++
>   >  3 files changed, 61 insertions(+), 2 deletions(-)
>   >
>   > diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h
>   > index 225a563..60e7a7e 100644
>   > --- a/arch/mips/include/asm/mach-loongson64/boot_param.h
>   > +++ b/arch/mips/include/asm/mach-loongson64/boot_param.h
>   > @@ -218,5 +218,6 @@ struct loongson_system_configuration {
>   >  extern struct efi_memory_map_loongson *loongson_memmap;
>   >  extern struct loongson_system_configuration loongson_sysconf;
>   >  extern struct board_devices *eboard;
>   > +extern u32 node_id_offset;
>   >
>   >  #endif
>   > diff --git a/arch/mips/loongson64/dma.c b/arch/mips/loongson64/dma.c
>   > index 5e86635..997c257 100644
>   > --- a/arch/mips/loongson64/dma.c
>   > +++ b/arch/mips/loongson64/dma.c
>   > @@ -2,24 +2,69 @@
>   >  #include <linux/dma-direct.h>
>   >  #include <linux/init.h>
>   >  #include <linux/swiotlb.h>
>   > +#include <boot_param.h>
>   >
>   > -dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
>   > +struct loongson_dma_ops {
>   > +    dma_addr_t (*phys_to_dma)(struct device *dev, phys_addr_t paddr);
>   > +    phys_addr_t (*dma_to_phys)(struct device *dev, dma_addr_t daddr);
>   > +};
>   > +
>   > +struct loongson_dma_ops loongson_dma;
>   > +
>   > +dma_addr_t __rs780e_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);
>   >  }
>   >
>   > -phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr)
>   > +dma_addr_t __ls7a_phys_to_dma(struct device *dev, phys_addr_t paddr)
>   > +{
>   > +    long nid = (paddr >> 44) & 0x3;
>   > +
>   > +    return ((nid << 44) ^ paddr) | (nid << (36 + node_id_offset));
>   > +}
>   > +
>   > +
>   > +dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
>   > +{
>   > +    return loongson_dma.phys_to_dma(dev, paddr);
>   > +}
>   > +
>   > +phys_addr_t __rs780e_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);
>   >  }
>   >
>   > +phys_addr_t __ls7a_dma_to_phys(struct device *dev, dma_addr_t daddr)
>   > +{
>   > +    long nid = (daddr >> (36 + node_id_offset)) & 0x3;
>   > +
>   > +    return ((nid << (36 + node_id_offset)) ^ daddr) | (nid << 44);
>   > +}
>   > +
>   > +phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t daddr)
>   > +{
>   > +    return loongson_dma.dma_to_phys(dev, daddr);
>   > +}
>   > +
>   >  void __init plat_swiotlb_setup(void)
>   >  {
>   >      swiotlb_init(1);
>   > +
>   > +    if (strstr(eboard->name, "780E")) {
>   > +        loongson_dma.phys_to_dma = __rs780e_phys_to_dma;
>   > +        loongson_dma.dma_to_phys = __rs780e_dma_to_phys;
>   > +    }
>   > +
>   > +    if (strstr(eboard->name, "7A1000")) {
>   > +        loongson_dma.phys_to_dma = __ls7a_phys_to_dma;
>   > +        loongson_dma.dma_to_phys = __ls7a_dma_to_phys;
>   > +    }
>   >  }
>   > diff --git a/arch/mips/loongson64/init.c b/arch/mips/loongson64/init.c
>   > index 5ac1a0f..dd8463d 100644
>   > --- a/arch/mips/loongson64/init.c
>   > +++ b/arch/mips/loongson64/init.c
>   > @@ -12,6 +12,11 @@
>   >  #include <asm/fw/fw.h>
>   >
>   >  #include <loongson.h>
>   > +#include <boot_param.h>
>   > +
>   > +#define NODE_ID_OFFSET_ADDR     0x90000E001001041CULL
>   > +
>   > +u32 node_id_offset;
>   >
>   >  static void __init mips_nmi_setup(void)
>   >  {
>   > @@ -23,6 +28,11 @@ static void __init mips_nmi_setup(void)
>   >      flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
>   >  }
>   >
>   > +static void ls7a_early_config(void)
>   > +{
>   > +    node_id_offset = (*(u32 *)NODE_ID_OFFSET_ADDR >> 8) & 0x1F;
>
> Please avoid raw pointer. Use readl/writel instead.

OK, I will do it.

Thanks,

Tiezhu Yang

>
>   > +}
>   > +
>   >  void __init prom_init(void)
>   >  {
>   >      fw_init_cmdline();
>   > @@ -32,6 +42,9 @@ void __init prom_init(void)
>   >      set_io_port_base((unsigned long)
>   >          ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
>   >
>   > +    if (strstr(eboard->name, "7A1000"))
>   > +        ls7a_early_config();
>   > +
>   >      prom_init_numa_memory();
>   >
>   >      /* Hardcode to CPU UART 0 */
>   > --
>   > 2.1.0
>   >
>   >


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: 回复:[PATCH 5/6] MIPS: Loongson: Add PCI support for 7A1000
  2020-03-09  8:47   ` 回复:[PATCH " Jiaxun Yang
@ 2020-03-10  3:03     ` Tiezhu Yang
  0 siblings, 0 replies; 21+ messages in thread
From: Tiezhu Yang @ 2020-03-10  3:03 UTC (permalink / raw)
  To: Jiaxun Yang
  Cc: Thomas Bogendoerfer, Huacai Chen, Bjorn Helgaas, Jens Axboe,
	linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li,
	Jianmin Lv

On 03/09/2020 04:47 PM, Jiaxun Yang wrote:
>
>   ---- 在 星期一, 2020-03-09 16:23:25 Tiezhu Yang <yangtiezhu@loongson.cn> 撰写 ----
>   > Add PCI support for 7A1000 to detect PCI device.
>   >
>   > Co-developed-by: Jianmin Lv <lvjianmin@loongson.cn>
>   > Signed-off-by: Jianmin Lv <lvjianmin@loongson.cn>
>   > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
>   > ---
>   >  arch/mips/include/asm/mach-loongson64/pci.h |   1 +
>   >  arch/mips/loongson64/pci.c                  |  12 ++-
>   >  arch/mips/pci/Makefile                      |   2 +-
>   >  arch/mips/pci/ops-loongson3-ls7a.c          | 132 ++++++++++++++++++++++++++++
>   >  4 files changed, 143 insertions(+), 4 deletions(-)
>   >  create mode 100644 arch/mips/pci/ops-loongson3-ls7a.c
>   >
>   > diff --git a/arch/mips/include/asm/mach-loongson64/pci.h b/arch/mips/include/asm/mach-loongson64/pci.h
>   > index 8b59d64..42c9744 100644
>   > --- a/arch/mips/include/asm/mach-loongson64/pci.h
>   > +++ b/arch/mips/include/asm/mach-loongson64/pci.h
>   > @@ -8,6 +8,7 @@
>   >  #define __ASM_MACH_LOONGSON64_PCI_H_
>   >
>   >  extern struct pci_ops loongson_pci_ops;
>   > +extern struct pci_ops loongson_ls7a_pci_ops;
>   >
>   >  /* this is an offset from mips_io_port_base */
>   >  #define LOONGSON_PCI_IO_START    0x00004000UL
>   > diff --git a/arch/mips/loongson64/pci.c b/arch/mips/loongson64/pci.c
>   > index e84ae20..b79368f 100644
>   > --- a/arch/mips/loongson64/pci.c
>   > +++ b/arch/mips/loongson64/pci.c
>   > @@ -23,8 +23,8 @@ static struct resource loongson_pci_io_resource = {
>   >      .flags    = IORESOURCE_IO,
>   >  };
>   >
>   > -static struct pci_controller  loongson_pci_controller = {
>   > -    .pci_ops    = &loongson_pci_ops,
>   > +static struct pci_controller loongson_pci_controller = {
>   > +    .pci_ops    = NULL,
>   >      .io_resource    = &loongson_pci_io_resource,
>   >      .mem_resource    = &loongson_pci_mem_resource,
>   >      .mem_offset    = 0x00000000UL,
>   > @@ -36,6 +36,11 @@ extern int sbx00_acpi_init(void);
>   >
>   >  static int __init pcibios_init(void)
>   >  {
>   > +    if (strstr(eboard->name, "780E"))
>   > +        loongson_pci_controller.pci_ops = &loongson_pci_ops;
>   > +
>   > +    if (strstr(eboard->name, "7A1000"))
>   > +        loongson_pci_controller.pci_ops = &loongson_ls7a_pci_ops;
>
> Please do not check PCH type everywhere.

Yes, you are right.

>
>   >
>   >      loongson_pci_controller.io_map_base = mips_io_port_base;
>   >      loongson_pci_mem_resource.start = loongson_sysconf.pci_mem_start_addr;
>   > @@ -43,7 +48,8 @@ static int __init pcibios_init(void)
>   >
>   >      register_pci_controller(&loongson_pci_controller);
>   >
>   > -    sbx00_acpi_init();
>   > +    if (strstr(eboard->name, "780E"))
>   > +        sbx00_acpi_init();
>   >
>   >      return 0;
>   >  }
>   > diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
>   > index 342ce10..7256bb1 100644
>   > --- a/arch/mips/pci/Makefile
>   > +++ b/arch/mips/pci/Makefile
>   > @@ -35,7 +35,7 @@ obj-$(CONFIG_LASAT)        += pci-lasat.o
>   >  obj-$(CONFIG_MIPS_COBALT)    += fixup-cobalt.o
>   >  obj-$(CONFIG_LEMOTE_FULOONG2E)    += fixup-fuloong2e.o ops-loongson2.o
>   >  obj-$(CONFIG_LEMOTE_MACH2F)    += fixup-lemote2f.o ops-loongson2.o
>   > -obj-$(CONFIG_MACH_LOONGSON64)    += fixup-loongson3.o ops-loongson3.o
>   > +obj-$(CONFIG_MACH_LOONGSON64)    += fixup-loongson3.o ops-loongson3.o ops-loongson3-ls7a.o
>   >  obj-$(CONFIG_MIPS_MALTA)    += fixup-malta.o pci-malta.o
>   >  obj-$(CONFIG_PMC_MSP7120_GW)    += fixup-pmcmsp.o ops-pmcmsp.o
>   >  obj-$(CONFIG_PMC_MSP7120_EVAL)    += fixup-pmcmsp.o ops-pmcmsp.o
>   > diff --git a/arch/mips/pci/ops-loongson3-ls7a.c b/arch/mips/pci/ops-loongson3-ls7a.c
>   > new file mode 100644
>   > index 0000000..4ed6c40
>   > --- /dev/null
>   > +++ b/arch/mips/pci/ops-loongson3-ls7a.c
>   > @@ -0,0 +1,132 @@
>   > +// SPDX-License-Identifier: GPL-2.0
>   > +/*
>   > + * Copyright (C) 2020 Loongson Technology Corporation Limited
>   > + *
>   > + * Author: Jianmin Lv <lvjianmin@loongson.cn>
>   > + * Author: Tiezhu Yang <yangtiezhu@loongson.cn>
>   > + */
>   > +
>   > +#include <linux/types.h>
>   > +#include <linux/pci.h>
>   > +#include <linux/kernel.h>
>   > +
>   > +#include <asm/mips-boards/bonito64.h>
>
> Why we need this?

I will check it, if it is useless, I will remove it.

>
>   > +
>   > +#include <loongson.h>
>   > +
>   > +#define PCI_ACCESS_READ 0
>   > +#define PCI_ACCESS_WRITE 1
>   > +
>   > +#define HT1LO_PCICFG_BASE 0x1a000000
>   > +#define HT1LO_PCICFG_BASE_TP1 0x1b000000
>   > +
>   > +#define HT1LO_PCICFG_BASE_EXT 0xefe00000000
>   > +#define HT1LO_PCICFG_BASE_TP1_EXT 0xefe10000000
>   > +
>   > +static 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 (busnum == 0 &&
>   > +            reg == PCI_CLASS_REVISION && *data == 0x06000001)
>   > +            *data = (PCI_CLASS_BRIDGE_PCI << 16) | (*data & 0xffff);
>
> It should be a part of quirk. Not a part of accessing.
>
>   > +
>   > +        if (*data == 0xffffffff) {
>   > +            *data = -1;
>   > +            return PCIBIOS_DEVICE_NOT_FOUND;
>   > +        }
>   > +    }
>   > +
>   > +    return PCIBIOS_SUCCESSFUL;
>   > +}
>   > +
>   > +static int ls7a_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn,
>   > +                 int where, int size, u32 *val)
>   > +{
>   > +    int ret;
>   > +    u32 data = 0;
>   > +
>   > +    ret = ls7a_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
>   > +    if (ret != PCIBIOS_SUCCESSFUL)
>   > +        return ret;
>   > +
>   > +    if (size == 1)
>   > +        *val = (data >> ((where & 3) << 3)) & 0xff;
>   > +    else if (size == 2)
>   > +        *val = (data >> ((where & 3) << 3)) & 0xffff;
>   > +    else
>   > +        *val = data;
>
> That  loggic seems identical with RS780E one, can we reuse them?

OK, I will do it.

Thanks,

Tiezhu Yang

>
>> +
>   > +    return PCIBIOS_SUCCESSFUL;
>   > +}
>   > +
>   > +static int ls7a_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn,
>   > +                  int where, int size, u32 val)
>   > +{
>   > +    int ret;
>   > +    u32 data = 0;
>   > +
>   > +    if (size == 4)
>   > +        data = val;
>   > +    else {
>   > +        ret = ls7a_pci_config_access(PCI_ACCESS_READ, bus,
>   > +                        devfn, where, &data);
>   > +        if (ret != PCIBIOS_SUCCESSFUL)
>   > +            return ret;
>   > +
>   > +        if (size == 1)
>   > +            data = (data & ~(0xff << ((where & 3) << 3))) |
>   > +                (val << ((where & 3) << 3));
>   > +        else if (size == 2)
>   > +            data = (data & ~(0xffff << ((where & 3) << 3))) |
>   > +                (val << ((where & 3) << 3));
>   > +    }
>   > +
>   > +    ret = ls7a_pci_config_access(PCI_ACCESS_WRITE, bus,
>   > +                    devfn, where, &data);
>   > +
>   > +    return ret;
>   > +}
>   > +
>   > +struct pci_ops loongson_ls7a_pci_ops = {
>   > +    .read = ls7a_pci_pcibios_read,
>   > +    .write = ls7a_pci_pcibios_write
>   > +};
>   > --
>   > 2.1.0
>   >
>   >


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: 回复:[PATCH 6/6] MIPS: Loongson: Add support for 7A1000 interrupt controller
  2020-03-09  9:07   ` 回复:[PATCH " Jiaxun Yang
@ 2020-03-10  4:28     ` Tiezhu Yang
  0 siblings, 0 replies; 21+ messages in thread
From: Tiezhu Yang @ 2020-03-10  4:28 UTC (permalink / raw)
  To: Jiaxun Yang
  Cc: Thomas Bogendoerfer, Huacai Chen, Bjorn Helgaas, Jens Axboe,
	linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li,
	Jianmin Lv

On 03/09/2020 05:07 PM, Jiaxun Yang wrote:
>   ---- 在 星期一, 2020-03-09 16:23:26 Tiezhu Yang <yangtiezhu@loongson.cn> 撰写 ----
>   > Use interrupt model to support interrupt controller of Loongson
>   > 7A1000 bridge chip.
>
> This patch seems clueless for me.
> Partly beacuse you're hijacking what should be done by irq domain and irqchip.
> Variuous of abbreviations makes me frustrated, so I didn't dig in to your logic deeper.
> See my review comments below.

This implementation is an abstract interrupt model, it is
easily extended to support the new Loongson bridge chip
7A2000, 7A3000, ...

I will modify the code to make it more clear about the
following comments you mentioned.

Thanks,

Tiezhu Yang

>
>   >
>   > Co-developed-by: Jianmin Lv <lvjianmin@loongson.cn>
>   > Signed-off-by: Jianmin Lv <lvjianmin@loongson.cn>
>   > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
>   > ---
>   >  arch/mips/include/asm/mach-loongson64/ioaicu.h | 166 ++++++++++++++
>   >  arch/mips/include/asm/mach-loongson64/irq.h    |   2 +
>   >  arch/mips/loongson64/Makefile                  |   2 +-
>   >  arch/mips/loongson64/ioaicu.c                  | 305 +++++++++++++++++++++++++
>   >  arch/mips/loongson64/irq.c                     |  20 +-
>   >  arch/mips/loongson64/smp.c                     |  11 +-
>   >  6 files changed, 497 insertions(+), 9 deletions(-)
>   >  create mode 100644 arch/mips/include/asm/mach-loongson64/ioaicu.h
>   >  create mode 100644 arch/mips/loongson64/ioaicu.c
>   >
>   > diff --git a/arch/mips/include/asm/mach-loongson64/ioaicu.h b/arch/mips/include/asm/mach-loongson64/ioaicu.h
>   > new file mode 100644
>   > index 0000000..e55de0d
>   > --- /dev/null
>   > +++ b/arch/mips/include/asm/mach-loongson64/ioaicu.h
>   > @@ -0,0 +1,166 @@
>   > +/* SPDX-License-Identifier: GPL-2.0 */
>   > +/*
>   > + * Copyright (C) 2020 Loongson Technology Corporation Limited
>   > + *
>   > + * Author: Jianmin Lv <lvjianmin@loongson.cn>
>   > + * Author: Tiezhu Yang <yangtiezhu@loongson.cn>
>   > + */
>   > +
>   > +#ifndef _ASM_LOONGSON_IOAICU_H
>   > +#define _ASM_LOONGSON_IOAICU_H
>   > +
>   > +#define LS_CFG_BASE    0x3ff00000
>
> Here your "_BASE" is using phys addr.
>
>   > +#define LS_CFG_OFF(x)    ((void *)TO_UNCAC(LS_CFG_BASE) + (x))
>   > +
>   > +#define LS_IRC_BASE    LS_CFG_OFF(0x1400)
>   > +#define LS_IRC_OFF(x)    (LS_IRC_BASE + x)
>   > +
>   > +#define LS_IRC_ENT(x)    LS_IRC_OFF(x)
>   > +#define LS_IRC_EN    LS_IRC_OFF(0x24)
>   > +#define LS_IRC_ENSET    LS_IRC_OFF(0x28)
>   > +
>   > +#define MAX_IOAICUS        16
>   > +#define LS3A_MAX_IPI_IRQ    26
>   > +#define LS3A_MAX_IO_VECTOR    64
>   > +#define LS3A_MAX_IO_IRQ        256
>   > +
>   > +#define LS7A_PCH_REG_BASE    0x10000000
>   > +#define LS7A_IOAICU_IRQ_BASE    64
>   > +
>   > +#define IOAICU_BASE    0x90000e0000000000ULL
>
> But here your "_BASE" is using virt addr.
>
>   > +#define IOAICU_IMR    0x20
>   > +#define IOAICU_IER    0x60
>   > +#define IOAICU_ICR    0x80
>   > +#define IOAICU_IRR    0x100
>   > +#define IOAICU_ISR    0x3a0
>   > +#define IOAICU_IPR    0x3e0
>   > +
>   > +#define USE_HTH_INT0    0x1
>
> What's that?
>
>   > +
>   > +#define LS3A_IOIRQ2VECTOR(irq) (irq - LS3A_MAX_IO_VECTOR)
>   > +#define LS3A_VECTOR2IOIRQ(vector) (vector + LS3A_MAX_IO_VECTOR)
>   > +
>   > +struct ioaicu_config {
>   > +    unsigned char aicuid;
>   > +    unsigned char aicuver;
>   > +    unsigned int aicuaddr;
>   > +};
>   > +
>   > +struct ioaicu_gsi {
>   > +    u32 gsi_base;
>   > +    u32 gsi_end;
>   > +};
>
> What's meant by GSI?
>
>   > +
>   > +struct ioaicu {
>   > +    int nr_registers;
>   > +    struct ioaicu_config config;
>   > +    struct ioaicu_gsi gsi_config;
>   > +};
>   > +
>   > +struct loongson_irq_dispatch_ops {
>   > +    void (*irq_dispatch)(void);
>   > +};
>   > +
>   > +extern void setup_ioaicu(void);
>   > +extern struct ioaicu ioaicus[MAX_IOAICUS];
>   > +extern struct loongson_irq_dispatch_ops loongson_pch;
>   > +extern unsigned short ls3a_ipi_pos2irq[LS3A_MAX_IO_VECTOR];
>   > +
>   > +extern void loongson3_send_irq_by_ipi(int cpu, int irqs);
>   > +extern int plat_set_irq_affinity(struct irq_data *d,
>   > +                 const struct cpumask *affinity, bool force);
>   > +
>   > +static inline unsigned long ioaicu_read64(unsigned int aicu, unsigned int reg)
>   > +{
>   > +    unsigned long addr = ioaicus[aicu].config.aicuaddr;
>   > +
>   > +    return *(unsigned long *)(IOAICU_BASE + addr + reg);
>
> Please avoid raw pointer. Also applied to rest of the patch.
>
>   > +}
>   > +
>   > +static inline void ioaicu_write64(unsigned int aicu,
>   > +                  unsigned int reg, unsigned long value)
>   > +{
>   > +    unsigned long addr = ioaicus[aicu].config.aicuaddr;
>   > +    *(unsigned long *)(IOAICU_BASE + addr + reg) = value;
>> +}
>   > +
>   > +static inline unsigned char ioaicu_read8(unsigned int aicu, unsigned int reg)
>   > +{
>   > +    unsigned long addr = ioaicus[aicu].config.aicuaddr;
>   > +
>   > +    return *(unsigned char *)(IOAICU_BASE + addr + reg);
>   > +}
>   > +
>   > +static inline void ioaicu_write8(unsigned int aicu,
>   > +                 unsigned int reg, unsigned char value)
>   > +{
>   > +    unsigned long addr = ioaicus[aicu].config.aicuaddr;
>   > +    *(unsigned char *)(IOAICU_BASE + addr + reg) = value;
>   > +}
>   > +
>   > +static inline int ioaicu_get_redir_entries(int ioaicu)
>   > +{
>   > +    return 64;
>
> Why not a macro?
>
>   > +}
>   > +
>   > +static inline struct ioaicu_gsi *ioaicu_gsi_routing(int ioaicu_idx)
>   > +{
>   > +    return &ioaicus[ioaicu_idx].gsi_config;
>   > +}
>   > +
>   > +static inline int ioaicu_id(int ioaicu_idx)
>   > +{
>   > +    return ioaicus[ioaicu_idx].config.aicuid;
>   > +}
>   > +
>   > +static inline unsigned int ioaicu_addr(int ioaicu_idx)
>   > +{
>   > +    return ioaicus[ioaicu_idx].config.aicuaddr;
>   > +}
>   > +
>   > +#define ioaicu_ver(ioaicu_idx) ioaicus[ioaicu_idx].config.aicuver
>   > +
>   > +static inline void ls64_conf_write64(u64 val64, void __iomem *addr)
>   > +{
>   > +    asm volatile (
>   > +    "    .set push\n"
>   > +    "    .set noreorder\n"
>   > +    "    sd    %[v], (%[hw])\n"
>   > +    "    lb    $0, (%[hw])\n"
>   > +    "    .set pop\n"
>   > +    :
>   > +    : [hw] "r" (addr),  [v] "r" (val64)
>   > +    );
>   > +}
>
> What are you doing here? I assume you're trying to workaround hardware bug?
> Is it an io barrier? If so, please make it as a part of general io.h.
>
>   > +
>   > +static inline void ls64_conf_write32(u32 val, void __iomem *addr)
>   > +{
>   > +    asm volatile (
>   > +    "    .set push\n"
>   > +    "    .set noreorder\n"
>   > +    "    sw    %[v], (%[hw])\n"
>   > +    "    lb    $0, (%[hw])\n"
>   > +    "    .set pop\n"
>   > +    :
>   > +    : [hw] "r" (addr), [v] "r" (val)
>   > +    );
>   > +}
>   > +
>   > +static inline void ls64_conf_write8(u8 val, void __iomem *addr)
>   > +{
>   > +    asm volatile (
>   > +    "    .set push\n"
>   > +    "    .set noreorder\n"
>   > +    "    sb    %[v], (%[hw])\n"
>   > +    "    lb    $0, (%[hw])\n"
>   > +    "    .set pop\n"
>   > +    :
>   > +    : [hw] "r" (addr), [v] "r" (val)
>   > +    );
>   > +}
>   > +
>   > +#define ls64_conf_read64(addr) readq(addr)
>   > +#define ls64_conf_read32(addr) readl(addr)
>   > +#define ls64_conf_read8(addr) readb(addr)
>   > +
>   > +#endif /* _ASM_LOONGSON_IOAICU_H */
>   > diff --git a/arch/mips/include/asm/mach-loongson64/irq.h b/arch/mips/include/asm/mach-loongson64/irq.h
>   > index 73a8991..10568be 100644
>   > --- a/arch/mips/include/asm/mach-loongson64/irq.h
>   > +++ b/arch/mips/include/asm/mach-loongson64/irq.h
>   > @@ -4,6 +4,8 @@
>   >
>   >  #include <boot_param.h>
>   >
>   > +#define NR_IRQS (64 + 256)
>   > +
>   >  /* cpu core interrupt numbers */
>   >  #define MIPS_CPU_IRQ_BASE 56
>   >
>   > diff --git a/arch/mips/loongson64/Makefile b/arch/mips/loongson64/Makefile
>   > index 7821891..3db50c6 100644
>   > --- a/arch/mips/loongson64/Makefile
>   > +++ b/arch/mips/loongson64/Makefile
>   > @@ -3,7 +3,7 @@
>   >  # Makefile for Loongson-3 family machines
>   >  #
>   >  obj-$(CONFIG_MACH_LOONGSON64) += irq.o cop2-ex.o platform.o acpi_init.o dma.o \
>   > -                setup.o init.o env.o time.o reset.o \
>   > +                setup.o init.o env.o time.o reset.o ioaicu.o \
>   >
>   >  obj-$(CONFIG_SMP)    += smp.o
>   >  obj-$(CONFIG_NUMA)    += numa.o
>   > diff --git a/arch/mips/loongson64/ioaicu.c b/arch/mips/loongson64/ioaicu.c
>   > new file mode 100644
>   > index 0000000..904ac75
>   > --- /dev/null
>   > +++ b/arch/mips/loongson64/ioaicu.c
>   > @@ -0,0 +1,305 @@
>   > +// SPDX-License-Identifier: GPL-2.0
>   > +/*
>   > + * Copyright (C) 2020 Loongson Technology Corporation Limited
>   > + *
>   > + * Author: Jianmin Lv <lvjianmin@loongson.cn>
>   > + * Author: Tiezhu Yang <yangtiezhu@loongson.cn>
>   > + */
>   > +
>   > +#include <loongson.h>
>   > +#include <ioaicu.h>
>   > +
>   > +static DEFINE_SPINLOCK(pch_irq_lock);
>   > +DECLARE_BITMAP(ls3a_ipi_in_use, LS3A_MAX_IPI_IRQ);
>   > +struct loongson_irq_dispatch_ops loongson_pch;
>   > +struct ioaicu ioaicus[MAX_IOAICUS];
>   > +
>   > +unsigned short ls3a_ipi_pos2irq[LS3A_MAX_IO_VECTOR] = {
>   > +                    [0 ... LS3A_MAX_IO_VECTOR-1] = -1 };
>   > +unsigned char ls3a_ipi_irq2pos[LS3A_MAX_IO_IRQ] = {
>   > +                    [0 ... LS3A_MAX_IO_IRQ-1] = -1 };
>   > +unsigned int cpu_for_irq[LS3A_MAX_IO_IRQ] = {
>   > +                    [0 ... LS3A_MAX_IO_IRQ-1] = -1};
>   > +
>   > +u32 gsi_top;
>   > +int nr_ioaicus;
>   > +#define for_each_ioaicu(idx)    \
>   > +    for ((idx) = 0; (idx) < nr_ioaicus; (idx)++)
>   > +#define for_each_pin(idx, pin)    \
>   > +    for ((pin) = 0; (pin) < ioaicus[(idx)].nr_registers; (pin)++)
>   > +
>   > +static int bad_ioaicu(unsigned long address)
>   > +{
>   > +    if (nr_ioaicus >= MAX_IOAICUS) {
>   > +        pr_warn("WARNING: Max # of I/O AICUs (%d) exceeded (found %d), skipping\n",
>   > +            MAX_IOAICUS, nr_ioaicus);
>   > +        return 1;
>   > +    }
>   > +
>   > +    if (!address) {
>   > +        pr_warn("WARNING: Bogus (zero) I/O AICU address found in table, skipping!\n");
>   > +        return 1;
>   > +    }
>   > +
>   > +    return 0;
>   > +}
>   > +
>   > +static void register_ioaicu(int id, u32 address, u32 gsi_base)
>   > +{
>   > +    int idx = 0;
>   > +    int entries;
>   > +    struct ioaicu_gsi *gsi_cfg;
>   > +
>   > +    if (bad_ioaicu(address))
>   > +        return;
>   > +
>   > +    idx = nr_ioaicus;
>   > +    ioaicus[idx].config.aicuaddr = address;
>   > +    ioaicus[idx].config.aicuid = id;
>   > +    ioaicus[idx].config.aicuver = 0;
>   > +
>   > +    entries = ioaicu_get_redir_entries(idx);
>   > +    gsi_cfg = ioaicu_gsi_routing(idx);
>   > +    gsi_cfg->gsi_base = gsi_base;
>   > +    gsi_cfg->gsi_end = gsi_base + entries - 1;
>   > +
>   > +    ioaicus[idx].nr_registers = entries;
>   > +
>   > +    if (gsi_cfg->gsi_end >= gsi_top)
>   > +        gsi_top = gsi_cfg->gsi_end + 1;
>   > +
>   > +    pr_info("IOAICU[%d]: aicu_id %d, version %d, address 0x%x, GSI %d-%d\n",
>   > +        idx, ioaicu_id(idx), ioaicu_ver(idx), ioaicu_addr(idx),
>   > +        gsi_cfg->gsi_base, gsi_cfg->gsi_end);
>   > +
>   > +    nr_ioaicus++;
>   > +}
>   > +
>   > +static int find_ioaicu(u32 gsi)
>   > +{
>   > +    int i;
>   > +
>   > +    if (nr_ioaicus == 0)
>   > +        return -1;
>   > +
>   > +    for_each_ioaicu(i) {
>   > +        struct ioaicu_gsi *gsi_cfg = ioaicu_gsi_routing(i);
>   > +
>   > +        if (gsi >= gsi_cfg->gsi_base && gsi <= gsi_cfg->gsi_end)
>   > +            return i;
>   > +    }
>   > +
>   > +    pr_err("ERROR: Unable to locate IOAICU for GSI %d\n", gsi);
>   > +
>   > +    return -1;
>   > +}
>   > +
>   > +static int pch_create_dirq(unsigned int irq)
>   > +{
>   > +    unsigned long flags;
>   > +    int pos;
>   > +
>   > +    spin_lock_irqsave(&pch_irq_lock, flags);
>   > +again:
>   > +    pos = find_first_zero_bit(ls3a_ipi_in_use, LS3A_MAX_IPI_IRQ);
>   > +    if (pos == LS3A_MAX_IPI_IRQ) {
>   > +        spin_unlock_irqrestore(&pch_irq_lock, flags);
>   > +        return -ENOSPC;
>   > +    }
>
> See Hierarchy IRQ domain, that's what you need.
>
>
>   > +
>   > +    if (test_and_set_bit(pos, ls3a_ipi_in_use))
>   > +        goto again;
>   > +
>   > +    ls3a_ipi_pos2irq[pos] = irq;
>   > +    ls3a_ipi_irq2pos[LS3A_IOIRQ2VECTOR(irq)] = pos;
>   > +    spin_unlock_irqrestore(&pch_irq_lock, flags);
>   > +
>   > +    return 0;
>   > +}
>   > +
>   > +static void pch_destroy_dirq(unsigned int irq)
>   > +{
>   > +    unsigned long flags;
>   > +    int pos;
>   > +
>   > +    spin_lock_irqsave(&pch_irq_lock, flags);
>   > +    pos = ls3a_ipi_irq2pos[LS3A_IOIRQ2VECTOR(irq)];
>   > +    if (pos >= 0) {
>   > +        clear_bit(pos, ls3a_ipi_in_use);
>   > +        ls3a_ipi_irq2pos[LS3A_IOIRQ2VECTOR(irq)] = -1;
>   > +        ls3a_ipi_pos2irq[pos] = -1;
>   > +    }
>   > +    spin_unlock_irqrestore(&pch_irq_lock, flags);
>   > +}
>   > +
>   > +static void line_mask_pch_irq(struct irq_data *d)
>   > +{
>   > +    unsigned long flags, data;
>   > +    unsigned int ioaicu;
>   > +    unsigned long irq_nr = d->irq;
>   > +
>   > +    ioaicu = (unsigned int)find_ioaicu((u32)irq_nr);
>   > +
>   > +    spin_lock_irqsave(&pch_irq_lock, flags);
>   > +    data = ioaicu_read64(ioaicu, IOAICU_IMR);
>   > +    data |= (1ULL << LS3A_IOIRQ2VECTOR(irq_nr));
>   > +    ioaicu_write64(ioaicu, IOAICU_IMR, data);
>   > +    spin_unlock_irqrestore(&pch_irq_lock, flags);
>   > +}
>   > +
>   > +static void line_unmask_pch_irq(struct irq_data *d)
>   > +{
>   > +    unsigned long flags, data;
>   > +    unsigned int ioaicu;
>   > +    unsigned long irq_nr = d->irq;
>   > +
>   > +    ioaicu = (unsigned int)find_ioaicu((u32)irq_nr);
>   > +
>   > +    spin_lock_irqsave(&pch_irq_lock, flags);
>   > +    data = ioaicu_read64(ioaicu, IOAICU_IMR);
>   > +    data &= ~(1ULL << LS3A_IOIRQ2VECTOR(irq_nr));
>   > +    ioaicu_write64(ioaicu, IOAICU_IMR, data);
>   > +    spin_unlock_irqrestore(&pch_irq_lock, flags);
>   > +}
>   > +
>   > +static unsigned int line_startup_pch_irq(struct irq_data *d)
>   > +{
>   > +    pch_create_dirq(d->irq);
>   > +    line_unmask_pch_irq(d);
>   > +
>   > +    return 0;
>   > +}
>   > +
>   > +static void line_shutdown_pch_irq(struct irq_data *d)
>   > +{
>   > +    line_mask_pch_irq(d);
>   > +    pch_destroy_dirq(d->irq);
>   > +}
>   > +
>   > +static struct irq_chip ioaicu_line_chip = {
>   > +    .name            = "IOAICU-LINE",
>   > +    .irq_mask        = line_mask_pch_irq,
>   > +    .irq_unmask        = line_unmask_pch_irq,
>   > +    .irq_startup        = line_startup_pch_irq,
>   > +    .irq_shutdown        = line_shutdown_pch_irq,
>   > +    .irq_set_affinity    = plat_set_irq_affinity,
>   > +};
>   > +
>   > +static void line_route_init(void)
>   > +{
>   > +    unsigned int dummy;
>   > +
>   > +    /* route 3A CPU0 INT0 to node0 core0 INT1(IP3) */
>   > +    dummy = LOONGSON_INT_COREx_INTy(loongson_sysconf.boot_cpu_id, 1);
>   > +    ls64_conf_write8(dummy, LS_IRC_ENT(0));
>   > +
>   > +    dummy = ls64_conf_read32(LS_IRC_EN);
>   > +    dummy |= 0x1;
>   > +    ls64_conf_write32(dummy, LS_IRC_ENSET);
>   > +}
>   > +
>   > +static void init_pin_route(unsigned int ioaicu, int vec)
>   > +{
>   > +    ioaicu_write8(ioaicu, IOAICU_IRR + vec, USE_HTH_INT0);
>   > +}
>   > +
>   > +static void init_ioaicu_pin(unsigned int ioaicu, int pin,
>   > +                struct irq_chip *pirq_chip)
>   > +{
>   > +    init_pin_route(ioaicu, LS3A_IOIRQ2VECTOR(pin));
>   > +    irq_set_chip_and_handler(pin, pirq_chip, handle_level_irq);
>   > +}
>   > +
>   > +static void setup_ioaicu_irqs(struct irq_chip *pirq_chip)
>   > +{
>   > +    unsigned int ioaicu, pin;
>   > +    struct ioaicu_gsi *gsi_cfg;
>   > +
>   > +    for_each_ioaicu(ioaicu) {
>   > +        ioaicu_write64(ioaicu, IOAICU_IER, 0);
>   > +        ioaicu_write64(ioaicu, IOAICU_IPR, (1ULL << 59));
>   > +        ioaicu_write64(ioaicu, IOAICU_ISR, 0);
>   > +        ioaicu_write64(ioaicu, IOAICU_IMR, -1ULL);
>   > +        ioaicu_write64(ioaicu, IOAICU_ICR, -1ULL);
>   > +    }
>   > +
>   > +    for (ioaicu = 0; ioaicu < nr_ioaicus; ioaicu++) {
>   > +        for (pin = 0; pin < ioaicus[ioaicu].nr_registers; pin++) {
>   > +            gsi_cfg = ioaicu_gsi_routing(ioaicu);
>   > +            init_ioaicu_pin(ioaicu,
>   > +                    pin + gsi_cfg->gsi_base, pirq_chip);
>   > +        }
>   > +    }
>   > +}
>   > +
>   > +static void handle_irqs(unsigned long long irqs, int i)
>   > +{
>   > +    unsigned int irq;
>   > +    struct irq_data *irqd;
>   > +    struct cpumask affinity;
>   > +    int cpu = smp_processor_id();
>   > +
>   > +    while (irqs) {
>   > +        irq = __ffs(irqs);
>   > +        irqs &= ~(1ULL<<irq);
>   > +        irq += (i << 6);
>   > +
>   > +        /* handled by local core */
>   > +        if (ls3a_ipi_irq2pos[irq] == (unsigned char)-1) {
>   > +            do_IRQ(LS3A_VECTOR2IOIRQ(irq));
>   > +            continue;
>   > +        }
>   > +
>   > +        irqd = irq_get_irq_data(LS3A_VECTOR2IOIRQ(irq));
>   > +        cpumask_and(&affinity, irqd->common->affinity, cpu_active_mask);
>   > +        if (cpumask_empty(&affinity)) {
>   > +            do_IRQ(LS3A_VECTOR2IOIRQ(irq));
>   > +            continue;
>   > +        }
>   > +
>   > +        cpu_for_irq[irq] = cpumask_next(cpu_for_irq[irq], &affinity);
>   > +        if (cpu_for_irq[irq] >= nr_cpu_ids)
>   > +            cpu_for_irq[irq] = cpumask_first(&affinity);
>   > +
>   > +        if (cpu_for_irq[irq] == cpu) {
>   > +            do_IRQ(LS3A_VECTOR2IOIRQ(irq));
>   > +            continue;
>   > +        }
>   > +
>   > +        /* balanced by other cores */
>   > +        loongson3_send_irq_by_ipi(cpu_for_irq[irq],
>   > +                      (0x1 << (ls3a_ipi_irq2pos[irq])));
>   > +    }
>   > +}
>   > +
>   > +static void ioaicu_line_dispatch(void)
>   > +{
>   > +    unsigned long flags;
>   > +    unsigned int ioaicu;
>   > +    unsigned long long intstatus;
>   > +    unsigned long long intmask;
>   > +
>   > +    for_each_ioaicu(ioaicu) {
>   > +        /* read irq status register */
>   > +        intstatus = ioaicu_read64(ioaicu, IOAICU_ISR);
>   > +
>   > +        spin_lock_irqsave(&pch_irq_lock, flags);
>   > +        intmask = ioaicu_read64(ioaicu, IOAICU_IMR);
>   > +        intmask |= intstatus;
>   > +        ioaicu_write64(ioaicu, IOAICU_IMR, intmask);
>   > +        intmask = ioaicu_read64(ioaicu, IOAICU_IMR);
>   > +        spin_unlock_irqrestore(&pch_irq_lock, flags);
>   > +
>   > +        handle_irqs(intstatus, 0);
>   > +    }
>   > +}
>   > +
>   > +/* ioaicu: input/output advanced interrupt control unit */
>   > +void __init setup_ioaicu(void)
>   > +{
>   > +    register_ioaicu(0, LS7A_PCH_REG_BASE, LS7A_IOAICU_IRQ_BASE);
>   > +
>   > +    line_route_init();
>   > +    setup_ioaicu_irqs(&ioaicu_line_chip);
>   > +    loongson_pch.irq_dispatch = ioaicu_line_dispatch;
>   > +}
>   > diff --git a/arch/mips/loongson64/irq.c b/arch/mips/loongson64/irq.c
>   > index 79ad797..988f21f 100644
>   > --- a/arch/mips/loongson64/irq.c
>   > +++ b/arch/mips/loongson64/irq.c
>   > @@ -1,6 +1,7 @@
>   >  // SPDX-License-Identifier: GPL-2.0
>   >  #include <loongson.h>
>   >  #include <irq.h>
>   > +#include <ioaicu.h>
>   >  #include <linux/interrupt.h>
>   >  #include <linux/init.h>
>   >
>   > @@ -71,6 +72,8 @@ static void ht_irqdispatch(void)
>   >              continue;
>   >          }
>   >
>   > +        ls3a_ipi_pos2irq[ht_irq[i]] = ht_irq[i];
>   > +
>   >          /* balanced by other cores */
>   >          loongson3_send_irq_by_ipi(irq_cpu[ht_irq[i]], (0x1 << ht_irq[i]));
>   >      }
>   > @@ -91,7 +94,7 @@ asmlinkage void plat_irq_dispatch(void)
>   >          loongson3_ipi_interrupt(NULL);
>   >  #endif
>   >      if (pending & CAUSEF_IP3)
>   > -        ht_irqdispatch();
>   > +        loongson_pch.irq_dispatch();
>   >      if (pending & CAUSEF_IP2)
>   >          do_IRQ(LOONGSON_UART_IRQ);
>   >      if (pending & UNUSED_IPS) {
>   > @@ -137,11 +140,18 @@ void __init arch_init_irq(void)
>   >
>   >      clear_c0_status(ST0_IM | ST0_BEV);
>   >
>   > -    irq_router_init();
>   >      mips_cpu_irq_init();
>   > -    init_i8259_irqs();
>   > -    chip = irq_get_chip(I8259A_IRQ_BASE);
>   > -    chip->irq_set_affinity = plat_set_irq_affinity;
>   > +
>   > +    if (strstr(eboard->name, "780E")) {
>   > +        irq_router_init();
>   > +        init_i8259_irqs();
>   > +        loongson_pch.irq_dispatch = ht_irqdispatch;
>   > +        chip = irq_get_chip(I8259A_IRQ_BASE);
>   > +        chip->irq_set_affinity = plat_set_irq_affinity;
>   > +    }
>   > +
>   > +    if (strstr(eboard->name, "7A1000"))
>   > +        setup_ioaicu();
>
> Ahh... strstr again.
> Forgot to mention, you'd better make RS780E as fallback when no PCH type string
> found in eboard name. That's to Loongson's crappy specification, 2/5 of my Loongson
> boards didn't set their board name correctly.
>
>   >
>   >      irq_set_chip_and_handler(LOONGSON_UART_IRQ,
>   >              &loongson_irq_chip, handle_percpu_irq);
>   > diff --git a/arch/mips/loongson64/smp.c b/arch/mips/loongson64/smp.c
>   > index de8e074..0720df7 100644
>   > --- a/arch/mips/loongson64/smp.c
>   > +++ b/arch/mips/loongson64/smp.c
>   > @@ -20,6 +20,7 @@
>   >  #include <loongson.h>
>   >  #include <loongson_regs.h>
>   >  #include <workarounds.h>
>   > +#include <ioaicu.h>
>   >
>   >  #include "smp.h"
>   >
>   > @@ -336,10 +337,14 @@ void loongson3_ipi_interrupt(struct pt_regs *regs)
>   >      }
>   >
>   >      if (irqs) {
>   > -        int irq;
>   > +        int irq, irq1;
>   > +
>   >          while ((irq = ffs(irqs))) {
>   > -            do_IRQ(irq-1);
>   > -            irqs &= ~(1<<(irq-1));
>   > +            irq1 = ls3a_ipi_pos2irq[irq - 1];
>   > +            if (likely(irq1 != (unsigned short)-1)) {
>   > +                do_IRQ(irq1);
>   > +                irqs &= ~(1 << (irq - 1));
>   > +            }
>   >          }
>   >      }
>   >  }
>   > --
>   > 2.1.0
>   >
>   >


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: 回复:[PATCH 1/6] PCI: Add Loongson vendor ID and 7A1000 device IDs
  2020-03-10  2:37       ` Jiaxun Yang
@ 2020-03-10  9:28         ` Tiezhu Yang
  0 siblings, 0 replies; 21+ messages in thread
From: Tiezhu Yang @ 2020-03-10  9:28 UTC (permalink / raw)
  To: Jiaxun Yang
  Cc: Thomas Bogendoerfer, Huacai Chen, Bjorn Helgaas, Jens Axboe,
	linux-mips, linux-pci, linux-ide, linux-kernel, Xuefeng Li

On 03/10/2020 10:37 AM, Jiaxun Yang wrote:
>
> 于 2020年3月10日 GMT+08:00 上午10:31:56, Tiezhu Yang <yangtiezhu@loongson.cn> 写到:
>> On 03/09/2020 04:50 PM, Jiaxun Yang wrote:
>>>    ---- 在 星期一, 2020-03-09 16:23:21 Tiezhu Yang
>> <yangtiezhu@loongson.cn> 撰写 ----
>>>    > Add the Loongson vendor ID and 7A1000 device IDs to pci_ids.h
>>>    > to be used by the controller driver in the future.
>>>    >
>>>    > The Loongson IDs can be found at the following link:
>>>    >
>> https://git.kernel.org/pub/scm/utils/pciutils/pciutils.git/tree/pci.ids
>>>    >
>>>    > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
>>>    > ---
>>>    >  include/linux/pci_ids.h | 18 ++++++++++++++++++
>>>    >  1 file changed, 18 insertions(+)
>>>    >
>>>    > diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
>>>    > index 352c0d7..0125ab4 100644
>>>    > --- a/include/linux/pci_ids.h
>>>    > +++ b/include/linux/pci_ids.h
>>>    > @@ -3113,4 +3113,22 @@
>>>    >
>>>    >  #define PCI_VENDOR_ID_NCUBE        0x10ff
>>>    >
>>>    > +#define PCI_VENDOR_ID_LOONGSON            0x0014
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_HT    0x7a00
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_APB    0x7a02
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_GMAC    0x7a03
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_OTG    0x7a04
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_DC    0x7a06
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_HDA    0x7a07
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_SATA    0x7a08
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_PCIE_X1    0x7a09
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_SPI    0x7a0b
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_LPC    0x7a0c
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_DMA    0x7a0f
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_EHCI    0x7a14
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_GPU    0x7a15
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_PCIE_X4    0x7a19
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_OHCI    0x7a24
>>>    > +#define PCI_DEVICE_ID_LOONGSON_7A1000_PCIE_X8    0x7a29
>>>
>>> Devices IDs are unlikely to be reused by mutiple subsystems, so
>> probably we don't need
>>> to add them here?
>> Hi Jiaxun,
>>
>> I think it is better to define the device IDs in pci_ids.h,
>> otherwise it seems a little disorganized.
> Please read the comment at the start of this file.
> New entries should be added only if they're shared by multiple drivers.
>
> That's the rule.
>
> And probably you can split these two patches into a new series
> as they're likely to be accepted.

OK, that makes sense.

Let me split the two patches 1/6 and 2/6 into a new series,
the first patch only adds the Loongson vendor ID to pci_ids.h.

Thanks,

Tiezhu Yang

>
> Thanks.
>
>> Thanks,
>>
>> Tiezhu Yang
>>
>>>    
>>>> +
>>>    >  #endif /* _LINUX_PCI_IDS_H */
>>>    > --
>>>    > 2.1.0
>>>    >
>>>    >


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 4/6] MIPS: Loongson: Add DMA support for 7A1000
  2020-03-09  8:23 ` [PATCH 4/6] MIPS: Loongson: Add DMA support for 7A1000 Tiezhu Yang
  2020-03-09  8:44   ` 回复:[PATCH " Jiaxun Yang
@ 2020-03-13  8:24   ` Christoph Hellwig
  2020-03-13  9:03     ` Tiezhu Yang
  1 sibling, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2020-03-13  8:24 UTC (permalink / raw)
  To: Tiezhu Yang
  Cc: Thomas Bogendoerfer, Huacai Chen, Jiaxun Yang, Bjorn Helgaas,
	Jens Axboe, linux-mips, linux-pci, linux-ide, linux-kernel,
	Xuefeng Li

On Mon, Mar 09, 2020 at 04:23:24PM +0800, Tiezhu Yang wrote:
> Implement __phys_to_dma() and __dma_to_phys() according to the
> node id offset in 7A1000 DMA route config register.

Can you just switch Loongson over to use the dma_pfn_offset field in
struct device?  I'd love to kill the __phys_to_dma and __dma_to_phys
hooks wherever possible.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 4/6] MIPS: Loongson: Add DMA support for 7A1000
  2020-03-13  8:24   ` [PATCH " Christoph Hellwig
@ 2020-03-13  9:03     ` Tiezhu Yang
  0 siblings, 0 replies; 21+ messages in thread
From: Tiezhu Yang @ 2020-03-13  9:03 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Thomas Bogendoerfer, Huacai Chen, Jiaxun Yang, Bjorn Helgaas,
	Jens Axboe, linux-mips, linux-pci, linux-ide, linux-kernel,
	Xuefeng Li

On 03/13/2020 04:24 PM, Christoph Hellwig wrote:
> On Mon, Mar 09, 2020 at 04:23:24PM +0800, Tiezhu Yang wrote:
>> Implement __phys_to_dma() and __dma_to_phys() according to the
>> node id offset in 7A1000 DMA route config register.
> Can you just switch Loongson over to use the dma_pfn_offset field in
> struct device?  I'd love to kill the __phys_to_dma and __dma_to_phys
> hooks wherever possible.

Hi Christoph,

Thanks for your suggestion, I will refactor the code.

Thanks,

Tiezhu Yang


^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2020-03-13  9:03 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-09  8:23 [PATCH 0/6] Add basic support for Loongson 7A1000 bridge chip Tiezhu Yang
2020-03-09  8:23 ` [PATCH 1/6] PCI: Add Loongson vendor ID and 7A1000 device IDs Tiezhu Yang
2020-03-09  8:50   ` 回复:[PATCH " Jiaxun Yang
2020-03-10  2:31     ` Tiezhu Yang
2020-03-10  2:37       ` Jiaxun Yang
2020-03-10  9:28         ` Tiezhu Yang
2020-03-09  8:23 ` [PATCH 2/6] AHCI: Add support for Loongson 7A1000 SATA controller Tiezhu Yang
2020-03-09  8:23 ` [PATCH 3/6] MIPS: Loongson: Use firmware arguments to get board name Tiezhu Yang
2020-03-09  8:36   ` 回复:[PATCH " Jiaxun Yang
2020-03-10  2:38     ` Tiezhu Yang
2020-03-09  8:23 ` [PATCH 4/6] MIPS: Loongson: Add DMA support for 7A1000 Tiezhu Yang
2020-03-09  8:44   ` 回复:[PATCH " Jiaxun Yang
2020-03-10  2:40     ` Tiezhu Yang
2020-03-13  8:24   ` [PATCH " Christoph Hellwig
2020-03-13  9:03     ` Tiezhu Yang
2020-03-09  8:23 ` [PATCH 5/6] MIPS: Loongson: Add PCI " Tiezhu Yang
2020-03-09  8:47   ` 回复:[PATCH " Jiaxun Yang
2020-03-10  3:03     ` Tiezhu Yang
2020-03-09  8:23 ` [PATCH 6/6] MIPS: Loongson: Add support for 7A1000 interrupt controller Tiezhu Yang
2020-03-09  9:07   ` 回复:[PATCH " Jiaxun Yang
2020-03-10  4:28     ` Tiezhu Yang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.