All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support
@ 2014-01-08  2:44 Huacai Chen
  2014-01-08  2:44 ` [PATCH V16 01/12] MIPS: Loongson: Add basic Loongson-3 definition Huacai Chen
                   ` (13 more replies)
  0 siblings, 14 replies; 55+ messages in thread
From: Huacai Chen @ 2014-01-08  2:44 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: John Crispin, Steven J. Hill, Aurelien Jarno, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Huacai Chen, Hongliang Tao, Hua Yan

This patchset is prepared for the next 3.14 release for Linux/MIPS.
Loongson-3 is a multi-core MIPS family CPU, it is MIPS64R2 compatible
and has the same IMP field (0x6300) as Loongson-2. These patches make
Linux kernel support Loongson-3 CPU and Loongson-3 based computers
(including Laptop, Mini-ITX, All-In-One PC, etc.)

V1 -> V2:
1, Split the first patch to two patches, one is constant definition and
   the other is CPU probing, cache initializing, etc.
2, Remove Kconfig options in the first 9 patches and put all of them in
   the 10th patch.
3, Use "make savedefconfig" to generate the new default config file.
4, Rework serial port support to use PORT and PORT_M macros.
5, Fix some compile warnings.

V2 -> V3:
1, Improve cache flushing code (use cpu_has_coherent_cache macro and
   remove #ifdef clauses).
2, Improve platform-specific code to correctly set driver's dma_mask/
   coherent_dma_mask so no longer need workarounds for each driver (
   SATA, graphics card, sound card, etc.)
3, Use PCI quirk to provide vgabios and loongson3_read_bios() go away.
4, Improve CPU hotplug code and split the poweroff failure related code
   to another patch (this issue affect all MIPS CPU, not only Loongson).
5, Some other small fixes.

V3 -> V4:
1, Include swiotlb.h in radeon_ttm.c if SWIOTLB configured.
2, Remove "Reviewed-by" in patches which are added by mistake.
3, Sync the code to upstream.

V4 -> V5:
1, Split the drm patch to three patches.
2, Use platform-specific pincfgs to replace old alsa quirks.

V5 -> V6:
1, For better management, two non-Loongson-specific patches are sent
   independently.
2, Introduce cpu_has_coherent_cache feature and split cache flushing
   changes to a separate patch.
3, Remove PRID_IMP_LOONGSON3 and use PRID_IMP_LOONGSON2 since they are
   the same.
4, Don't define RTC_ALWAYS_BCD for Loongson-3 since BCD format can be
   checked by RTC_CONTROL at runtime.
5, Don't modify dma-default.c for Loongson since it is unnecessary.
6, Don't define SAREA_MAX since it is useless.
7, Increase the default boost of internal mic for Lemote A1004.
8, Fix a #ifdef issue in dma-coherence.h.
9, Some other small fixes.

V6 -> V7:
1, Fix boot failure when NR_CPUS is more than present cpus.
2, Fix error messages after poweroff & reboot.
3, Update the default config file.
4, Sync the code to upstream.

V7 -> V8:
1, Add WEAK_ORDERING/WEAK_REORDERING_BEYOND_LLSC for Loongson-3.
2, Fix a deadlock of cpu-hotplug.
3, Include swiotlb.h in arch-specific code to avoid driver modification.
4, Remove the patch "drm: Handle io prot correctly for MIPS" since it
   is already in upstream code.
5, Remove the patch "ALSA: HDA: Make hda sound card usable for Loongson"
   since it is already in upstream code.
6, Use LZMA compression and do some adjustment of config file to reduce
   kernel size.

V8 -> V9:
1, Fix spurious IPI interrupt.
2, remove __dev* attributes since CONFIG_HOTPLUG is going away as an option.
3, Use dev_info() to print messages in fixup-loongson3.c.
4, Update the default config file.
5, Sync the code to upstream.

V9 -> V10:
1, Rework "Introduce and use cpu_has_coherent_cache feature".
2, Handle the case that System BIOS doesn't contain a VGA BIOS.
3, Sync the code to upstream (mostly indentation adjustment).

V10 -> V11:
1, Remove normal labels and useless nops in inline assembler.
2, Sync the code to upstream (Prepared for 3.12).

V11 -> V12:
1, Delete __cpuinit usage;
2, Remove the third patch since it is contentious;
3, Sync the code to upstream (Prepared for 3.13).

V12 -> V13:
1, Rework addrspace.h and spaces.h;
2, Move the modification of Platform from patch 1 to patch 12;
3, Sync the code to upstream (the mips-for-linux-next branch, for 3.13).

V13 -> V14:
1, Avoid spurious interrupt from serial port;
2, Drop CONFIG_LOONGSON_BIGMEM and use CONFIG_SWIOTLB directly;
3, Sync the code to upstream (the mips-for-linux-next branch, for 3.14).

V14 -> V15:
1, Fix duplicate ARCH_SPARSEMEM_ENABLE in Kconfig.

V15 -> V16:
1, Fix all coding style errors and most of warnings;
2, Make dma address translation simple and elegant;
3, Fix potential bugs in swiotlb code;
4, Rename UEFI firmware interface to LEFI;
5, Remove 32-bit kernel support temporarily;
6, Some other small fixes (thanks to Aurelien Jarno).

Huacai Chen(12):
 MIPS: Loongson: Add basic Loongson-3 definition.
 MIPS: Loongson: Add basic Loongson-3 CPU support.
 MIPS: Loongson 3: Add Lemote-3A machtypes definition.
 MIPS: Loongson: Add UEFI-like firmware interface (LEFI) support.
 MIPS: Loongson 3: Add HT-linked PCI support.
 MIPS: Loongson 3: Add IRQ init and dispatch support.
 MIPS: Loongson 3: Add serial port support.
 MIPS: Loongson: Add swiotlb to support big memory (>4GB).
 MIPS: Loongson: Add Loongson-3 Kconfig options.
 MIPS: Loongson 3: Add Loongson-3 SMP support.
 MIPS: Loongson 3: Add CPU hotplug support.
 MIPS: Loongson: Add a Loongson-3 default config file.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongliang Tao <taohl@lemote.com>
Signed-off-by: Hua Yan <yanh@lemote.com> 
---
 arch/mips/Kconfig                                  |   28 ++-
 arch/mips/configs/loongson3_defconfig              |  342 +++++++++++++++
 arch/mips/include/asm/addrspace.h                  |    2 +
 arch/mips/include/asm/bootinfo.h                   |   24 +-
 arch/mips/include/asm/cpu-type.h                   |    4 +
 arch/mips/include/asm/cpu.h                        |    5 +-
 arch/mips/include/asm/dma-mapping.h                |    5 +
 arch/mips/include/asm/mach-loongson/boot_param.h   |  159 +++++++
 .../mips/include/asm/mach-loongson/dma-coherence.h |   22 +-
 arch/mips/include/asm/mach-loongson/irq.h          |   29 ++
 arch/mips/include/asm/mach-loongson/loongson.h     |   28 +-
 arch/mips/include/asm/mach-loongson/machine.h      |    6 +
 arch/mips/include/asm/mach-loongson/pci.h          |    5 +
 arch/mips/include/asm/mach-loongson/spaces.h       |   13 +
 arch/mips/include/asm/module.h                     |    2 +
 arch/mips/include/asm/pgtable-bits.h               |    9 +
 arch/mips/include/asm/smp.h                        |    1 +
 arch/mips/kernel/cpu-probe.c                       |   14 +-
 arch/mips/loongson/Kconfig                         |   44 ++
 arch/mips/loongson/Makefile                        |    6 +
 arch/mips/loongson/Platform                        |    1 +
 arch/mips/loongson/common/Makefile                 |    5 +
 arch/mips/loongson/common/dma-swiotlb.c            |  165 ++++++++
 arch/mips/loongson/common/env.c                    |   64 +++-
 arch/mips/loongson/common/init.c                   |   12 +-
 arch/mips/loongson/common/machtype.c               |    4 +
 arch/mips/loongson/common/mem.c                    |   42 ++
 arch/mips/loongson/common/pci.c                    |    6 +-
 arch/mips/loongson/common/reset.c                  |   21 +
 arch/mips/loongson/common/serial.c                 |   26 +-
 arch/mips/loongson/common/setup.c                  |    8 +-
 arch/mips/loongson/common/uart_base.c              |    9 +-
 arch/mips/loongson/loongson-3/Makefile             |    6 +
 arch/mips/loongson/loongson-3/irq.c                |  140 ++++++
 arch/mips/loongson/loongson-3/smp.c                |  446 ++++++++++++++++++++
 arch/mips/loongson/loongson-3/smp.h                |   24 +
 arch/mips/mm/c-r4k.c                               |   59 +++
 arch/mips/mm/tlb-r4k.c                             |    5 +-
 arch/mips/mm/tlbex.c                               |    1 +
 arch/mips/pci/Makefile                             |    1 +
 arch/mips/pci/fixup-loongson3.c                    |   70 +++
 arch/mips/pci/ops-loongson3.c                      |  101 +++++
 42 files changed, 1905 insertions(+), 59 deletions(-)
 create mode 100644 arch/mips/configs/loongson3_defconfig
 create mode 100644 arch/mips/include/asm/mach-loongson/boot_param.h
 create mode 100644 arch/mips/include/asm/mach-loongson/irq.h
 create mode 100644 arch/mips/include/asm/mach-loongson/spaces.h
 create mode 100644 arch/mips/loongson/common/dma-swiotlb.c
 create mode 100644 arch/mips/loongson/loongson-3/Makefile
 create mode 100644 arch/mips/loongson/loongson-3/irq.c
 create mode 100644 arch/mips/loongson/loongson-3/smp.c
 create mode 100644 arch/mips/loongson/loongson-3/smp.h
 create mode 100644 arch/mips/pci/fixup-loongson3.c
 create mode 100644 arch/mips/pci/ops-loongson3.c
--
1.7.7.3

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

* [PATCH V16 01/12] MIPS: Loongson: Add basic Loongson-3 definition
  2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
@ 2014-01-08  2:44 ` Huacai Chen
  2014-01-08 19:58   ` Aurelien Jarno
  2014-01-08  2:44 ` [PATCH V16 02/12] MIPS: Loongson: Add basic Loongson-3 CPU support Huacai Chen
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 55+ messages in thread
From: Huacai Chen @ 2014-01-08  2:44 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: John Crispin, Steven J. Hill, Aurelien Jarno, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Huacai Chen, Hongliang Tao, Hua Yan

Loongson-3 is a multi-core MIPS family CPU, it support MIPS64R2 fully.
Loongson-3 has the same IMP field (0x6300) as Loongson-2.

Loongson-3 has a hardware-maintained cache, system software doesn't
need to maintain coherency.

Loongson-3A is the first revision of Loongson-3, and it is the quad-
core version of Loongson-2G. Loongson-3A has a simplified version named
Loongson-2Gq, the main difference between Loongson-3A/2Gq is 3A has two
HyperTransport controller but 2Gq has only one. HT0 is used for cross-
chip interconnection and HT1 is used to link PCI bus. Therefore, 2Gq
cannot support NUMA but 3A can. For software, Loongson-2Gq is simply
identified as Loongson-3A.

Exsisting Loongson family CPUs:
Loongson-1: Loongson-1A, Loongson-1B, they are 32-bit MIPS CPUs.
Loongson-2: Loongson-2E, Loongson-2F, Loongson-2G, they are 64-bit
            single-core MIPS CPUs.
Loongson-3: Loongson-3A(including so-called Loongson-2Gq), they are
            64-bit multi-core MIPS CPUs.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongliang Tao <taohl@lemote.com>
Signed-off-by: Hua Yan <yanh@lemote.com>
---
 arch/mips/include/asm/addrspace.h            |    2 ++
 arch/mips/include/asm/cpu.h                  |    5 +++--
 arch/mips/include/asm/mach-loongson/spaces.h |   13 +++++++++++++
 arch/mips/include/asm/module.h               |    2 ++
 arch/mips/include/asm/pgtable-bits.h         |    9 +++++++++
 5 files changed, 29 insertions(+), 2 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-loongson/spaces.h

diff --git a/arch/mips/include/asm/addrspace.h b/arch/mips/include/asm/addrspace.h
index 3f74545..41c030e 100644
--- a/arch/mips/include/asm/addrspace.h
+++ b/arch/mips/include/asm/addrspace.h
@@ -116,7 +116,9 @@
 #define K_CALG_UNCACHED		2
 #define K_CALG_NONCOHERENT	3
 #define K_CALG_COH_EXCL		4
+#ifndef K_CALG_COH_SHAREABLE
 #define K_CALG_COH_SHAREABLE	5
+#endif
 #define K_CALG_NOTUSED		6
 #define K_CALG_UNCACHED_ACCEL	7
 
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index d2035e1..7fffaf1 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -224,6 +224,7 @@
 #define PRID_REV_LOONGSON1B	0x0020
 #define PRID_REV_LOONGSON2E	0x0002
 #define PRID_REV_LOONGSON2F	0x0003
+#define PRID_REV_LOONGSON3A	0x0005
 
 /*
  * Older processors used to encode processor version and revision in two
@@ -295,8 +296,8 @@ enum cpu_type_enum {
 	 * MIPS64 class processors
 	 */
 	CPU_5KC, CPU_5KE, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2,
-	CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS, CPU_CAVIUM_OCTEON2,
-	CPU_CAVIUM_OCTEON3, CPU_XLR, CPU_XLP,
+	CPU_LOONGSON3, CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS,
+	CPU_CAVIUM_OCTEON2, CPU_CAVIUM_OCTEON3, CPU_XLR, CPU_XLP,
 
 	CPU_LAST
 };
diff --git a/arch/mips/include/asm/mach-loongson/spaces.h b/arch/mips/include/asm/mach-loongson/spaces.h
new file mode 100644
index 0000000..d368d95
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/spaces.h
@@ -0,0 +1,13 @@
+#ifndef __ASM_MACH_LOONGSON_SPACES_H_
+#define __ASM_MACH_LOONGSON_SPACES_H_
+
+#ifndef CAC_BASE
+#if defined(CONFIG_64BIT)
+#define CAC_BASE        _AC(0x9800000000000000, UL)
+#endif /* CONFIG_64BIT */
+#endif /* CONFIG_CAC_BASE */
+
+#define K_CALG_COH_SHAREABLE	3
+
+#include <asm/mach-generic/spaces.h>
+#endif
diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
index 44b705d..c2edae3 100644
--- a/arch/mips/include/asm/module.h
+++ b/arch/mips/include/asm/module.h
@@ -126,6 +126,8 @@ search_module_dbetables(unsigned long addr)
 #define MODULE_PROC_FAMILY "LOONGSON1 "
 #elif defined CONFIG_CPU_LOONGSON2
 #define MODULE_PROC_FAMILY "LOONGSON2 "
+#elif defined CONFIG_CPU_LOONGSON3
+#define MODULE_PROC_FAMILY "LOONGSON3 "
 #elif defined CONFIG_CPU_CAVIUM_OCTEON
 #define MODULE_PROC_FAMILY "OCTEON "
 #elif defined CONFIG_CPU_XLR
diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h
index 32aea48..e592f36 100644
--- a/arch/mips/include/asm/pgtable-bits.h
+++ b/arch/mips/include/asm/pgtable-bits.h
@@ -235,6 +235,15 @@ static inline uint64_t pte_to_entrylo(unsigned long pte_val)
 #define _CACHE_CACHABLE_NONCOHERENT (5<<_CACHE_SHIFT)
 #define _CACHE_UNCACHED_ACCELERATED (7<<_CACHE_SHIFT)
 
+#elif defined(CONFIG_CPU_LOONGSON3)
+
+/* Using COHERENT flag for NONCOHERENT doesn't hurt. */
+
+#define _CACHE_UNCACHED             (2<<_CACHE_SHIFT)  /* LOONGSON       */
+#define _CACHE_CACHABLE_NONCOHERENT (3<<_CACHE_SHIFT)  /* LOONGSON       */
+#define _CACHE_CACHABLE_COHERENT    (3<<_CACHE_SHIFT)  /* LOONGSON-3     */
+#define _CACHE_UNCACHED_ACCELERATED (7<<_CACHE_SHIFT)  /* LOONGSON       */
+
 #else
 
 #define _CACHE_CACHABLE_NO_WA	    (0<<_CACHE_SHIFT)  /* R4600 only	  */
-- 
1.7.7.3

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

* [PATCH V16 02/12] MIPS: Loongson: Add basic Loongson-3 CPU support
  2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
  2014-01-08  2:44 ` [PATCH V16 01/12] MIPS: Loongson: Add basic Loongson-3 definition Huacai Chen
@ 2014-01-08  2:44 ` Huacai Chen
  2014-01-08 19:58   ` Aurelien Jarno
  2014-01-08  2:44 ` [PATCH V16 03/12] MIPS: Loongson 3: Add Lemote-3A machtypes definition Huacai Chen
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 55+ messages in thread
From: Huacai Chen @ 2014-01-08  2:44 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: John Crispin, Steven J. Hill, Aurelien Jarno, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Huacai Chen, Hongliang Tao, Hua Yan

Basic Loongson-3 CPU support include CPU probing and TLB/cache
initializing.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongliang Tao <taohl@lemote.com>
Signed-off-by: Hua Yan <yanh@lemote.com>
---
 arch/mips/include/asm/cpu-type.h |    4 ++
 arch/mips/kernel/cpu-probe.c     |   14 ++++++--
 arch/mips/mm/c-r4k.c             |   59 ++++++++++++++++++++++++++++++++++++++
 arch/mips/mm/tlb-r4k.c           |    5 ++-
 arch/mips/mm/tlbex.c             |    1 +
 5 files changed, 77 insertions(+), 6 deletions(-)

diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h
index 4a402cc..a591e63 100644
--- a/arch/mips/include/asm/cpu-type.h
+++ b/arch/mips/include/asm/cpu-type.h
@@ -20,6 +20,10 @@ static inline int __pure __get_cpu_type(const int cpu_type)
 	case CPU_LOONGSON2:
 #endif
 
+#ifdef CONFIG_SYS_HAS_CPU_LOONGSON3
+	case CPU_LOONGSON3:
+#endif
+
 #ifdef CONFIG_SYS_HAS_CPU_LOONGSON1B
 	case CPU_LOONGSON1:
 #endif
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index c814287..4bc81b2 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -639,17 +639,23 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
 			     MIPS_CPU_LLSC;
 		c->tlbsize = 64;
 		break;
-	case PRID_IMP_LOONGSON2:
-		c->cputype = CPU_LOONGSON2;
-		__cpu_name[cpu] = "ICT Loongson-2";
-
+	case PRID_IMP_LOONGSON2: /* Loongson-2/3 have the same PRID_IMP field */
 		switch (c->processor_id & PRID_REV_MASK) {
 		case PRID_REV_LOONGSON2E:
+			c->cputype = CPU_LOONGSON2;
+			__cpu_name[cpu] = "ICT Loongson-2E";
 			set_elf_platform(cpu, "loongson2e");
 			break;
 		case PRID_REV_LOONGSON2F:
+			c->cputype = CPU_LOONGSON2;
+			__cpu_name[cpu] = "ICT Loongson-2F";
 			set_elf_platform(cpu, "loongson2f");
 			break;
+		case PRID_REV_LOONGSON3A:
+			c->cputype = CPU_LOONGSON3;
+			__cpu_name[cpu] = "ICT Loongson-3A";
+			set_elf_platform(cpu, "loongson3a");
+			break;
 		}
 
 		set_isa(c, MIPS_CPU_ISA_III);
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 73f02da..cc02527 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -348,6 +348,7 @@ static inline void local_r4k___flush_cache_all(void * args)
 {
 	switch (current_cpu_type()) {
 	case CPU_LOONGSON2:
+	case CPU_LOONGSON3:
 	case CPU_R4000SC:
 	case CPU_R4000MC:
 	case CPU_R4400SC:
@@ -1003,6 +1004,33 @@ static void probe_pcache(void)
 		c->dcache.waybit = 0;
 		break;
 
+	case CPU_LOONGSON3:
+		config1 = read_c0_config1();
+		lsize = (config1 >> 19) & 7;
+		if (lsize)
+			c->icache.linesz = 2 << lsize;
+		else
+			c->icache.linesz = 0;
+		c->icache.sets = 64 << ((config1 >> 22) & 7);
+		c->icache.ways = 1 + ((config1 >> 16) & 7);
+		icache_size = c->icache.sets *
+					  c->icache.ways *
+					  c->icache.linesz;
+		c->icache.waybit = 0;
+
+		lsize = (config1 >> 10) & 7;
+		if (lsize)
+			c->dcache.linesz = 2 << lsize;
+		else
+			c->dcache.linesz = 0;
+		c->dcache.sets = 64 << ((config1 >> 13) & 7);
+		c->dcache.ways = 1 + ((config1 >> 7) & 7);
+		dcache_size = c->dcache.sets *
+					  c->dcache.ways *
+					  c->dcache.linesz;
+		c->dcache.waybit = 0;
+		break;
+
 	default:
 		if (!(config & MIPS_CONF_M))
 			panic("Don't know how to probe P-caches on this cpu.");
@@ -1222,6 +1250,33 @@ static void __init loongson2_sc_init(void)
 	c->options |= MIPS_CPU_INCLUSIVE_CACHES;
 }
 
+static void __init loongson3_sc_init(void)
+{
+	struct cpuinfo_mips *c = &current_cpu_data;
+	unsigned int config2, lsize;
+
+	config2 = read_c0_config2();
+	lsize = (config2 >> 4) & 15;
+	if (lsize)
+		c->scache.linesz = 2 << lsize;
+	else
+		c->scache.linesz = 0;
+	c->scache.sets = 64 << ((config2 >> 8) & 15);
+	c->scache.ways = 1 + (config2 & 15);
+
+	scache_size = c->scache.sets *
+				  c->scache.ways *
+				  c->scache.linesz;
+	/* Loongson-3 has 4 cores, 1MB scache for each. scaches are shared */
+	scache_size *= 4;
+	c->scache.waybit = 0;
+	pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
+	       scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
+	if (scache_size)
+		c->options |= MIPS_CPU_INCLUSIVE_CACHES;
+	return;
+}
+
 extern int r5k_sc_init(void);
 extern int rm7k_sc_init(void);
 extern int mips_sc_init(void);
@@ -1274,6 +1329,10 @@ static void setup_scache(void)
 		loongson2_sc_init();
 		return;
 
+	case CPU_LOONGSON3:
+		loongson3_sc_init();
+		return;
+
 	case CPU_XLP:
 		/* don't need to worry about L2, fully coherent */
 		return;
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index da3b0b9..298f281 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -53,13 +53,14 @@ extern void build_tlb_refill_handler(void);
 #endif /* CONFIG_MIPS_MT_SMTC */
 
 /*
- * LOONGSON2 has a 4 entry itlb which is a subset of dtlb,
- * unfortrunately, itlb is not totally transparent to software.
+ * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb,
+ * unfortunately, itlb is not totally transparent to software.
  */
 static inline void flush_itlb(void)
 {
 	switch (current_cpu_type()) {
 	case CPU_LOONGSON2:
+	case CPU_LOONGSON3:
 		write_c0_diag(4);
 		break;
 	default:
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 183f2b5..f89124c 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -579,6 +579,7 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
 	case CPU_BMIPS4380:
 	case CPU_BMIPS5000:
 	case CPU_LOONGSON2:
+	case CPU_LOONGSON3:
 	case CPU_R5500:
 		if (m4kc_tlbp_war())
 			uasm_i_nop(p);
-- 
1.7.7.3

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

* [PATCH V16 03/12] MIPS: Loongson 3: Add Lemote-3A machtypes definition
  2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
  2014-01-08  2:44 ` [PATCH V16 01/12] MIPS: Loongson: Add basic Loongson-3 definition Huacai Chen
  2014-01-08  2:44 ` [PATCH V16 02/12] MIPS: Loongson: Add basic Loongson-3 CPU support Huacai Chen
@ 2014-01-08  2:44 ` Huacai Chen
  2014-01-08 19:58   ` Aurelien Jarno
  2014-01-08  2:44 ` [PATCH V16 04/12] MIPS: Loongson: Add UEFI-like firmware interface (LEFI) support Huacai Chen
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 55+ messages in thread
From: Huacai Chen @ 2014-01-08  2:44 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: John Crispin, Steven J. Hill, Aurelien Jarno, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Huacai Chen, Hongliang Tao, Hua Yan

Add four Loongson-3 based machine types:
MACH_LEMOTE_A1004/MACH_LEMOTE_A1201 are laptops;
MACH_LEMOTE_A1101 is mini-itx;
MACH_LEMOTE_A1205 is all-in-one machine.

The most significant differrent between A1004/A1201 and A1101/A1205 is
the laptops have EC but others don't.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongliang Tao <taohl@lemote.com>
Signed-off-by: Hua Yan <yanh@lemote.com>
---
 arch/mips/include/asm/bootinfo.h              |   24 +++++++++++++++---------
 arch/mips/include/asm/mach-loongson/machine.h |    6 ++++++
 arch/mips/loongson/common/machtype.c          |    4 ++++
 3 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index 4d2cdea..09956a0 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -61,15 +61,21 @@
 /*
  * Valid machtype for Loongson family
  */
-#define MACH_LOONGSON_UNKNOWN  0
-#define MACH_LEMOTE_FL2E       1
-#define MACH_LEMOTE_FL2F       2
-#define MACH_LEMOTE_ML2F7      3
-#define MACH_LEMOTE_YL2F89     4
-#define MACH_DEXXON_GDIUM2F10  5
-#define MACH_LEMOTE_NAS	       6
-#define MACH_LEMOTE_LL2F       7
-#define MACH_LOONGSON_END      8
+enum loongson_machine_type {
+	MACH_LOONGSON_UNKNOWN,
+	MACH_LEMOTE_FL2E,
+	MACH_LEMOTE_FL2F,
+	MACH_LEMOTE_ML2F7,
+	MACH_LEMOTE_YL2F89,
+	MACH_DEXXON_GDIUM2F10,
+	MACH_LEMOTE_NAS,
+	MACH_LEMOTE_LL2F,
+	MACH_LEMOTE_A1004,
+	MACH_LEMOTE_A1101,
+	MACH_LEMOTE_A1201,
+	MACH_LEMOTE_A1205,
+	MACH_LOONGSON_END
+};
 
 /*
  * Valid machtype for group INGENIC
diff --git a/arch/mips/include/asm/mach-loongson/machine.h b/arch/mips/include/asm/mach-loongson/machine.h
index 3810d5c..1b1f592 100644
--- a/arch/mips/include/asm/mach-loongson/machine.h
+++ b/arch/mips/include/asm/mach-loongson/machine.h
@@ -24,4 +24,10 @@
 
 #endif
 
+#ifdef CONFIG_LEMOTE_MACH3A
+
+#define LOONGSON_MACHTYPE MACH_LEMOTE_A1101
+
+#endif /* CONFIG_LEMOTE_MACH3A */
+
 #endif /* __ASM_MACH_LOONGSON_MACHINE_H */
diff --git a/arch/mips/loongson/common/machtype.c b/arch/mips/loongson/common/machtype.c
index 4becd4f..1a47979 100644
--- a/arch/mips/loongson/common/machtype.c
+++ b/arch/mips/loongson/common/machtype.c
@@ -27,6 +27,10 @@ static const char *system_types[] = {
 	[MACH_DEXXON_GDIUM2F10]		"dexxon-gdium-2f",
 	[MACH_LEMOTE_NAS]		"lemote-nas-2f",
 	[MACH_LEMOTE_LL2F]		"lemote-lynloong-2f",
+	[MACH_LEMOTE_A1004]		"lemote-3a-notebook-a1004",
+	[MACH_LEMOTE_A1101]		"lemote-3a-itx-a1101",
+	[MACH_LEMOTE_A1201]		"lemote-2gq-notebook-a1201",
+	[MACH_LEMOTE_A1205]		"lemote-2gq-aio-a1205",
 	[MACH_LOONGSON_END]		NULL,
 };
 
-- 
1.7.7.3

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

* [PATCH V16 04/12] MIPS: Loongson: Add UEFI-like firmware interface (LEFI) support
  2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
                   ` (2 preceding siblings ...)
  2014-01-08  2:44 ` [PATCH V16 03/12] MIPS: Loongson 3: Add Lemote-3A machtypes definition Huacai Chen
@ 2014-01-08  2:44 ` Huacai Chen
  2014-01-08 22:58   ` Aurelien Jarno
  2014-01-09 12:37     ` Alex Smith
  2014-01-08  2:44 ` [PATCH V16 05/12] MIPS: Loongson 3: Add HT-linked PCI support Huacai Chen
                   ` (9 subsequent siblings)
  13 siblings, 2 replies; 55+ messages in thread
From: Huacai Chen @ 2014-01-08  2:44 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: John Crispin, Steven J. Hill, Aurelien Jarno, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Huacai Chen, Hongliang Tao, Hua Yan

The new UEFI-like firmware interface (LEFI, i.e. Loongson Unified
Firmware Interface) has 3 advantages:

1, Firmware export a physical memory map which is similar to X86's
   E820 map, so prom_init_memory() will be more elegant that #ifdef
   clauses can be removed.
2, Firmware export a pci irq routing table, we no longer need pci
   irq routing fixup in kernel's code.
3, Firmware has a built-in vga bios, and its address is exported,
   the linux kernel no longer need an embedded blob.

With the LEFI interface, Loongson-3A/2G and all their successors can use
a unified kernel. All Loongson-based machines support this new interface
except 2E/2F series.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongliang Tao <taohl@lemote.com>
Signed-off-by: Hua Yan <yanh@lemote.com>
---
 arch/mips/include/asm/mach-loongson/boot_param.h |  159 ++++++++++++++++++++++
 arch/mips/include/asm/mach-loongson/loongson.h   |    4 +-
 arch/mips/loongson/common/env.c                  |   64 +++++++--
 arch/mips/loongson/common/init.c                 |    9 +-
 arch/mips/loongson/common/mem.c                  |   42 ++++++
 arch/mips/loongson/common/pci.c                  |    6 +-
 arch/mips/loongson/common/reset.c                |   21 +++
 7 files changed, 285 insertions(+), 20 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-loongson/boot_param.h

diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h
new file mode 100644
index 0000000..234c0eb
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/boot_param.h
@@ -0,0 +1,159 @@
+#ifndef __ASM_MACH_LOONGSON_BOOT_PARAM_H_
+#define __ASM_MACH_LOONGSON_BOOT_PARAM_H_
+
+#define SYSTEM_RAM_LOW		1
+#define SYSTEM_RAM_HIGH		2
+#define MEM_RESERVED		3
+#define PCI_IO			4
+#define PCI_MEM			5
+#define LOONGSON_CFG_REG	6
+#define VIDEO_ROM		7
+#define ADAPTER_ROM		8
+#define ACPI_TABLE		9
+#define MAX_MEMORY_TYPE		10
+
+#define LOONGSON3_BOOT_MEM_MAP_MAX 128
+struct efi_memory_map_loongson {
+	u16 vers;	/* version of efi_memory_map */
+	u32 nr_map;	/* number of memory_maps */
+	u32 mem_freq;	/* memory frequence */
+	struct mem_map {
+		u32 node_id;	/* node_id which memory attached to */
+		u32 mem_type;	/* system memory, pci memory, pci io, etc. */
+		u64 mem_start;	/* memory map start address */
+		u32 mem_size;	/* each memory_map size, not the total size */
+	} map[LOONGSON3_BOOT_MEM_MAP_MAX];
+} __packed;
+
+enum loongson_cpu_type {
+	Loongson_2E = 0,
+	Loongson_2F = 1,
+	Loongson_3A = 2,
+	Loongson_3B = 3,
+	Loongson_1A = 4,
+	Loongson_1B = 5
+};
+
+/*
+ * Capability and feature descriptor structure for MIPS CPU
+ */
+struct efi_cpuinfo_loongson {
+	u16 vers;     /* version of efi_cpuinfo_loongson */
+	u32 processor_id; /* PRID, e.g. 6305, 6306 */
+	u32 cputype;  /* Loongson_3A/3B, etc. */
+	u32 total_node;   /* num of total numa nodes */
+	u32 cpu_startup_core_id; /* Core id */
+	u32 cpu_clock_freq; /* cpu_clock */
+	u32 nr_cpus;
+} __packed;
+
+struct system_loongson {
+	u16 vers;     /* version of system_loongson */
+	u32 ccnuma_smp; /* 0: no numa; 1: has numa */
+	u32 sing_double_channel; /* 1:single; 2:double */
+} __packed;
+
+struct irq_source_routing_table {
+	u16 vers;
+	u16 size;
+	u16 rtr_bus;
+	u16 rtr_devfn;
+	u32 vendor;
+	u32 device;
+	u32 PIC_type;   /* conform use HT or PCI to route to CPU-PIC */
+	u64 ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */
+	u64 ht_enable;  /* irqs used in this PIC */
+	u32 node_id;    /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */
+	u64 pci_mem_start_addr;
+	u64 pci_mem_end_addr;
+	u64 pci_io_start_addr;
+	u64 pci_io_end_addr;
+	u64 pci_config_addr;
+} __packed;
+
+struct interface_info {
+	u16 vers; /* version of the specificition */
+	u16 size;
+	u8  flag;
+	char description[64];
+} __packed;
+
+#define MAX_RESOURCE_NUMBER 128
+struct resource_loongson {
+	u64 start; /* resource start address */
+	u64 end;   /* resource end address */
+	char name[64];
+	u32 flags;
+};
+
+struct archdev_data {};  /* arch specific additions */
+
+struct board_devices {
+	char name[64];    /* hold the device name */
+	u32 num_resources; /* number of device_resource */
+	/* for each device's resource */
+	struct resource_loongson resource[MAX_RESOURCE_NUMBER];
+	/* arch specific additions */
+	struct archdev_data archdata;
+};
+
+struct loongson_special_attribute {
+	u16 vers;     /* version of this special */
+	char special_name[64]; /* special_atribute_name */
+	u32 loongson_special_type; /* type of special device */
+	/* for each device's resource */
+	struct resource_loongson resource[MAX_RESOURCE_NUMBER];
+};
+
+struct loongson_params {
+	u64 memory_offset;	/* efi_memory_map_loongson struct offset */
+	u64 cpu_offset;		/* efi_cpuinfo_loongson struct offset */
+	u64 system_offset;	/* system_loongson struct offset */
+	u64 irq_offset;		/* irq_source_routing_table struct offset */
+	u64 interface_offset;	/* interface_info struct offset */
+	u64 special_offset;	/* loongson_special_attribute struct offset */
+	u64 boarddev_table_offset;  /* board_devices offset */
+};
+
+struct smbios_tables {
+	u16 vers;     /* version of smbios */
+	u64 vga_bios; /* vga_bios address */
+	struct loongson_params lp;
+};
+
+struct efi_reset_system_t {
+	u64 ResetCold;
+	u64 ResetWarm;
+	u64 ResetType;
+	u64 Shutdown;
+};
+
+struct efi_loongson {
+	u64 mps;	/* MPS table */
+	u64 acpi;	/* ACPI table (IA64 ext 0.71) */
+	u64 acpi20;	/* ACPI table (ACPI 2.0) */
+	struct smbios_tables smbios;	/* SM BIOS table */
+	u64 sal_systab;	/* SAL system table */
+	u64 boot_info;	/* boot info table */
+};
+
+struct boot_params {
+	struct efi_loongson efi;
+	struct efi_reset_system_t reset_system;
+};
+
+struct loongson_system_configuration {
+	u32 nr_cpus;
+	enum loongson_cpu_type cputype;
+	u64 ht_control_base;
+	u64 pci_mem_start_addr;
+	u64 pci_mem_end_addr;
+	u64 pci_io_base;
+	u64 restart_addr;
+	u64 poweroff_addr;
+	u64 vgabios_addr;
+};
+
+extern struct efi_memory_map_loongson *emap;
+extern struct loongson_system_configuration loongson_sysconf;
+#endif
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index b286534..5913ea0 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -24,8 +24,8 @@ extern void mach_prepare_reboot(void);
 extern void mach_prepare_shutdown(void);
 
 /* environment arguments from bootloader */
-extern unsigned long cpu_clock_freq;
-extern unsigned long memsize, highmemsize;
+extern u32 cpu_clock_freq;
+extern u32 memsize, highmemsize;
 
 /* loongson-specific command line, env and memory initialization */
 extern void __init prom_init_memory(void);
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
index 0a18fcf..ba2b6df 100644
--- a/arch/mips/loongson/common/env.c
+++ b/arch/mips/loongson/common/env.c
@@ -18,29 +18,37 @@
  * option) any later version.
  */
 #include <linux/module.h>
-
 #include <asm/bootinfo.h>
-
 #include <loongson.h>
+#include <boot_param.h>
+
+struct boot_params *boot_p;
+struct loongson_params *loongson_p;
+
+struct efi_cpuinfo_loongson *ecpu;
+struct efi_memory_map_loongson *emap;
+struct system_loongson *esys;
+struct irq_source_routing_table *eirq_source;
+struct loongson_system_configuration loongson_sysconf;
 
-unsigned long cpu_clock_freq;
+u32 cpu_clock_freq;
 EXPORT_SYMBOL(cpu_clock_freq);
-unsigned long memsize, highmemsize;
 
 #define parse_even_earlier(res, option, p)				\
 do {									\
 	unsigned int tmp __maybe_unused;				\
 									\
 	if (strncmp(option, (char *)p, strlen(option)) == 0)		\
-		tmp = strict_strtol((char *)p + strlen(option"="), 10, &res); \
+		tmp = kstrtou32((char *)p + strlen(option"="), 10, &res); \
 } while (0)
 
 void __init prom_init_env(void)
 {
 	/* pmon passes arguments in 32bit pointers */
-	int *_prom_envp;
-	unsigned long bus_clock;
 	unsigned int processor_id;
+
+#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
+	int *_prom_envp;
 	long l;
 
 	/* firmware arguments are initialized in head.S */
@@ -48,7 +56,6 @@ void __init prom_init_env(void)
 
 	l = (long)*_prom_envp;
 	while (l != 0) {
-		parse_even_earlier(bus_clock, "busclock", l);
 		parse_even_earlier(cpu_clock_freq, "cpuclock", l);
 		parse_even_earlier(memsize, "memsize", l);
 		parse_even_earlier(highmemsize, "highmemsize", l);
@@ -57,8 +64,38 @@ void __init prom_init_env(void)
 	}
 	if (memsize == 0)
 		memsize = 256;
-	if (bus_clock == 0)
-		bus_clock = 66000000;
+	pr_info("memsize=%ld, highmemsize=%ld\n", memsize, highmemsize);
+#else
+	/* firmware arguments are initialized in head.S */
+	boot_p = (struct boot_params *)fw_arg2;
+	loongson_p = &(boot_p->efi.smbios.lp);
+
+	ecpu = (struct efi_cpuinfo_loongson *)
+		((u64)loongson_p + loongson_p->cpu_offset);
+	emap = (struct efi_memory_map_loongson *)
+		((u64)loongson_p + loongson_p->memory_offset);
+	eirq_source = (struct irq_source_routing_table *)
+		((u64)loongson_p + loongson_p->irq_offset);
+
+	cpu_clock_freq = ecpu->cpu_clock_freq;
+	loongson_sysconf.cputype = ecpu->cputype;
+	loongson_sysconf.nr_cpus = ecpu->nr_cpus;
+	if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
+		loongson_sysconf.nr_cpus = NR_CPUS;
+
+	loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr;
+	loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
+	loongson_sysconf.pci_io_base = eirq_source->pci_io_start_addr;
+
+	loongson_sysconf.restart_addr = boot_p->reset_system.ResetWarm;
+	loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
+
+	loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
+	loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios;
+	pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
+		loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
+		loongson_sysconf.vgabios_addr);
+#endif
 	if (cpu_clock_freq == 0) {
 		processor_id = (&current_cpu_data)->processor_id;
 		switch (processor_id & PRID_REV_MASK) {
@@ -68,12 +105,13 @@ void __init prom_init_env(void)
 		case PRID_REV_LOONGSON2F:
 			cpu_clock_freq = 797000000;
 			break;
+		case PRID_REV_LOONGSON3A:
+			cpu_clock_freq = 900000000;
+			break;
 		default:
 			cpu_clock_freq = 100000000;
 			break;
 		}
 	}
-
-	pr_info("busclock=%ld, cpuclock=%ld, memsize=%ld, highmemsize=%ld\n",
-		bus_clock, cpu_clock_freq, memsize, highmemsize);
+	pr_info("CpuClock = %u\n", cpu_clock_freq);
 }
diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
index ae7af1f..81ba3b4 100644
--- a/arch/mips/loongson/common/init.c
+++ b/arch/mips/loongson/common/init.c
@@ -17,10 +17,6 @@ unsigned long __maybe_unused _loongson_addrwincfg_base;
 
 void __init prom_init(void)
 {
-	/* init base address of io space */
-	set_io_port_base((unsigned long)
-		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
-
 #ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
 	_loongson_addrwincfg_base = (unsigned long)
 		ioremap(LOONGSON_ADDRWINCFG_BASE, LOONGSON_ADDRWINCFG_SIZE);
@@ -28,6 +24,11 @@ void __init prom_init(void)
 
 	prom_init_cmdline();
 	prom_init_env();
+
+	/* init base address of io space */
+	set_io_port_base((unsigned long)
+		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
+
 	prom_init_memory();
 
 	/*init the uart base address */
diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c
index 8626a42..42b2431 100644
--- a/arch/mips/loongson/common/mem.c
+++ b/arch/mips/loongson/common/mem.c
@@ -11,9 +11,14 @@
 #include <asm/bootinfo.h>
 
 #include <loongson.h>
+#include <boot_param.h>
 #include <mem.h>
 #include <pci.h>
 
+#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
+
+u32 memsize, highmemsize;
+
 void __init prom_init_memory(void)
 {
 	add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
@@ -49,6 +54,43 @@ void __init prom_init_memory(void)
 #endif /* !CONFIG_64BIT */
 }
 
+#else /* CONFIG_LEFI_FIRMWARE_INTERFACE */
+
+void __init prom_init_memory(void)
+{
+	int i;
+	u32 node_id;
+	u32 mem_type;
+
+	/* parse memory information */
+	for (i = 0; i < emap->nr_map; i++) {
+		node_id = emap->map[i].node_id;
+		mem_type = emap->map[i].mem_type;
+
+		if (node_id == 0) {
+			switch (mem_type) {
+			case SYSTEM_RAM_LOW:
+				add_memory_region(emap->map[i].mem_start,
+					(u64)emap->map[i].mem_size << 20,
+					BOOT_MEM_RAM);
+				break;
+			case SYSTEM_RAM_HIGH:
+				add_memory_region(emap->map[i].mem_start,
+					(u64)emap->map[i].mem_size << 20,
+					BOOT_MEM_RAM);
+				break;
+			case MEM_RESERVED:
+				add_memory_region(emap->map[i].mem_start,
+					(u64)emap->map[i].mem_size << 20,
+					BOOT_MEM_RESERVED);
+				break;
+			}
+		}
+	}
+}
+
+#endif /* CONFIG_LEFI_FIRMWARE_INTERFACE */
+
 /* override of arch/mips/mm/cache.c: __uncached_access */
 int __uncached_access(struct file *file, unsigned long addr)
 {
diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson/common/pci.c
index fa77844..003ab4e 100644
--- a/arch/mips/loongson/common/pci.c
+++ b/arch/mips/loongson/common/pci.c
@@ -11,6 +11,7 @@
 
 #include <pci.h>
 #include <loongson.h>
+#include <boot_param.h>
 
 static struct resource loongson_pci_mem_resource = {
 	.name	= "pci memory space",
@@ -82,7 +83,10 @@ static int __init pcibios_init(void)
 	setup_pcimap();
 
 	loongson_pci_controller.io_map_base = mips_io_port_base;
-
+#ifdef CONFIG_LEFI_FIRMWARE_INTERFACE
+	loongson_pci_mem_resource.start = loongson_sysconf.pci_mem_start_addr;
+	loongson_pci_mem_resource.end = loongson_sysconf.pci_mem_end_addr;
+#endif
 	register_pci_controller(&loongson_pci_controller);
 
 	return 0;
diff --git a/arch/mips/loongson/common/reset.c b/arch/mips/loongson/common/reset.c
index 65bfbb5..a60715e 100644
--- a/arch/mips/loongson/common/reset.c
+++ b/arch/mips/loongson/common/reset.c
@@ -16,6 +16,7 @@
 #include <asm/reboot.h>
 
 #include <loongson.h>
+#include <boot_param.h>
 
 static inline void loongson_reboot(void)
 {
@@ -37,17 +38,37 @@ static inline void loongson_reboot(void)
 
 static void loongson_restart(char *command)
 {
+#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
 	/* do preparation for reboot */
 	mach_prepare_reboot();
 
 	/* reboot via jumping to boot base address */
 	loongson_reboot();
+#else
+	void (*fw_restart)(void) = (void *)loongson_sysconf.restart_addr;
+
+	fw_restart();
+	while (1) {
+		if (cpu_wait)
+			cpu_wait();
+	}
+#endif
 }
 
 static void loongson_poweroff(void)
 {
+#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
 	mach_prepare_shutdown();
 	unreachable();
+#else
+	void (*fw_poweroff)(void) = (void *)loongson_sysconf.poweroff_addr;
+
+	fw_poweroff();
+	while (1) {
+		if (cpu_wait)
+			cpu_wait();
+	}
+#endif
 }
 
 static void loongson_halt(void)
-- 
1.7.7.3

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

* [PATCH V16 05/12] MIPS: Loongson 3: Add HT-linked PCI support
  2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
                   ` (3 preceding siblings ...)
  2014-01-08  2:44 ` [PATCH V16 04/12] MIPS: Loongson: Add UEFI-like firmware interface (LEFI) support Huacai Chen
@ 2014-01-08  2:44 ` Huacai Chen
  2014-01-08 22:58   ` Aurelien Jarno
  2014-01-08  2:44 ` [PATCH V16 06/12] MIPS: Loongson 3: Add IRQ init and dispatch support Huacai Chen
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 55+ messages in thread
From: Huacai Chen @ 2014-01-08  2:44 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: John Crispin, Steven J. Hill, Aurelien Jarno, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Huacai Chen, Hongliang Tao, Hua Yan

Loongson family machines use Hyper-Transport bus for inter-core
connection and device connection. The PCI bus is a subordinate
linked at HT1.

With LEFI firmware interface, We don't need fixup for PCI irq routing
(except providing a VBIOS of the integrated GPU).

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongliang Tao <taohl@lemote.com>
Signed-off-by: Hua Yan <yanh@lemote.com>
---
 arch/mips/include/asm/mach-loongson/loongson.h |    7 ++
 arch/mips/include/asm/mach-loongson/pci.h      |    5 +
 arch/mips/pci/Makefile                         |    1 +
 arch/mips/pci/fixup-loongson3.c                |   70 ++++++++++++++++
 arch/mips/pci/ops-loongson3.c                  |  101 ++++++++++++++++++++++++
 5 files changed, 184 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/pci/fixup-loongson3.c
 create mode 100644 arch/mips/pci/ops-loongson3.c

diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index 5913ea0..f0367ff 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/kconfig.h>
+#include <boot_param.h>
 
 /* loongson internal northbridge initialization */
 extern void bonito_irq_init(void);
@@ -101,7 +102,13 @@ static inline void do_perfcnt_IRQ(void)
 #define LOONGSON_PCICFG_BASE	0x1fe80000
 #define LOONGSON_PCICFG_SIZE	0x00000800	/* 2K */
 #define LOONGSON_PCICFG_TOP	(LOONGSON_PCICFG_BASE+LOONGSON_PCICFG_SIZE-1)
+
+#if defined(CONFIG_HT_PCI)
+#define LOONGSON_PCIIO_BASE	loongson_sysconf.pci_io_base
+#else
 #define LOONGSON_PCIIO_BASE	0x1fd00000
+#endif
+
 #define LOONGSON_PCIIO_SIZE	0x00100000	/* 1M */
 #define LOONGSON_PCIIO_TOP	(LOONGSON_PCIIO_BASE+LOONGSON_PCIIO_SIZE-1)
 
diff --git a/arch/mips/include/asm/mach-loongson/pci.h b/arch/mips/include/asm/mach-loongson/pci.h
index bc99dab..1212774 100644
--- a/arch/mips/include/asm/mach-loongson/pci.h
+++ b/arch/mips/include/asm/mach-loongson/pci.h
@@ -40,8 +40,13 @@ extern struct pci_ops loongson_pci_ops;
 #else	/* loongson2f/32bit & loongson2e */
 
 /* this pci memory space is mapped by pcimap in pci.c */
+#ifdef CONFIG_CPU_LOONGSON3
+#define LOONGSON_PCI_MEM_START	0x40000000UL
+#define LOONGSON_PCI_MEM_END	0x7effffffUL
+#else
 #define LOONGSON_PCI_MEM_START	LOONGSON_PCILO1_BASE
 #define LOONGSON_PCI_MEM_END	(LOONGSON_PCILO1_BASE + 0x04000000 * 2)
+#endif
 /* this is an offset from mips_io_port_base */
 #define LOONGSON_PCI_IO_START	0x00004000UL
 
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 719e455..5475859 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -29,6 +29,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_LEMOTE_MACH3A)	+= fixup-loongson3.o ops-loongson3.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/fixup-loongson3.c b/arch/mips/pci/fixup-loongson3.c
new file mode 100644
index 0000000..4a8477d
--- /dev/null
+++ b/arch/mips/pci/fixup-loongson3.c
@@ -0,0 +1,70 @@
+/*
+ * fixup-loongson3.c
+ *
+ * Copyright (C) 2012 Lemote, Inc.
+ * Author: Xiang Yu, xiangy@lemote.com
+ *         Chen Huacai, chenhc@lemote.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ * WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ * USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the  GNU General Public License along
+ * with this program; if not, write  to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/pci.h>
+#include <boot_param.h>
+
+static void print_fixup_info(const struct pci_dev *pdev)
+{
+	dev_info(&pdev->dev, "Device %x:%x, irq %d\n",
+			pdev->vendor, pdev->device, pdev->irq);
+}
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	print_fixup_info(dev);
+	return dev->irq;
+}
+
+static void pci_fixup_radeon(struct pci_dev *pdev)
+{
+	if (pdev->resource[PCI_ROM_RESOURCE].start)
+		return;
+
+	if (!loongson_sysconf.vgabios_addr)
+		return;
+
+	pdev->resource[PCI_ROM_RESOURCE].start =
+		loongson_sysconf.vgabios_addr;
+	pdev->resource[PCI_ROM_RESOURCE].end   =
+		loongson_sysconf.vgabios_addr + 256*1024 - 1;
+	pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_COPY;
+
+	dev_info(&pdev->dev, "BAR %d: assigned %pR for Radeon ROM\n",
+			PCI_ROM_RESOURCE, &pdev->resource[PCI_ROM_RESOURCE]);
+}
+
+DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
+				PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_radeon);
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return 0;
+}
diff --git a/arch/mips/pci/ops-loongson3.c b/arch/mips/pci/ops-loongson3.c
new file mode 100644
index 0000000..077eafa
--- /dev/null
+++ b/arch/mips/pci/ops-loongson3.c
@@ -0,0 +1,101 @@
+#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
+
+static int loongson3_pci_config_access(unsigned char access_type,
+		struct pci_bus *bus, unsigned int devfn,
+		int where, u32 *data)
+{
+	unsigned char busnum = bus->number;
+	u_int64_t addr, type;
+	void *addrp;
+	int device = PCI_SLOT(devfn);
+	int function = PCI_FUNC(devfn);
+	int reg = where & ~3;
+
+	addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
+	if (busnum == 0) {
+		if (device > 31)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+		addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE) | (addr & 0xffff));
+		type = 0;
+
+	} else {
+		addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE_TP1) | (addr));
+		type = 0x10000;
+	}
+
+	if (access_type == PCI_ACCESS_WRITE)
+		writel(cpu_to_le32(*data), addrp);
+	else {
+		*data = le32_to_cpu(readl(addrp));
+		if (*data == 0xffffffff) {
+			*data = -1;
+			return PCIBIOS_DEVICE_NOT_FOUND;
+		}
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int loongson3_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+				 int where, int size, u32 *val)
+{
+	u32 data = 0;
+	int ret = loongson3_pci_config_access(PCI_ACCESS_READ,
+			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 loongson3_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+				  int where, int size, u32 val)
+{
+	u32 data = 0;
+	int ret;
+
+	if (size == 4)
+		data = val;
+	else {
+		ret = loongson3_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 = loongson3_pci_config_access(PCI_ACCESS_WRITE,
+			bus, devfn, where, &data);
+
+	return ret;
+}
+
+struct pci_ops loongson_pci_ops = {
+	.read = loongson3_pci_pcibios_read,
+	.write = loongson3_pci_pcibios_write
+};
-- 
1.7.7.3

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

* [PATCH V16 06/12] MIPS: Loongson 3: Add IRQ init and dispatch support
  2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
                   ` (4 preceding siblings ...)
  2014-01-08  2:44 ` [PATCH V16 05/12] MIPS: Loongson 3: Add HT-linked PCI support Huacai Chen
@ 2014-01-08  2:44 ` Huacai Chen
  2014-01-08 22:58   ` Aurelien Jarno
  2014-01-09 12:52     ` Alex Smith
  2014-01-08  2:44 ` [PATCH V16 07/12] MIPS: Loongson 3: Add serial port support Huacai Chen
                   ` (7 subsequent siblings)
  13 siblings, 2 replies; 55+ messages in thread
From: Huacai Chen @ 2014-01-08  2:44 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: John Crispin, Steven J. Hill, Aurelien Jarno, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Huacai Chen, Hongliang Tao, Hua Yan

IRQ routing path of Loongson-3:
Devices(most) --> I8259 --> HT Controller --> IRQ Routing Table --> CPU
                                                  ^
                                                  |
Device(legacy devices such as UART) --> Bonito ---|

IRQ Routing Table route 32 INTs to CPU's INT0~INT3(IP2~IP5 of CP0), 32
INTs include 16 HT INTs(mostly), 4 PCI INTs, 1 LPC INT, etc. IP6 is used
for IPI and IP7 is used for internal MIPS timer. LOONGSON_INT_ROUTER_*
are IRQ Routing Table registers.

I8259 IRQs are 1:1 mapped to HT1 INTs. LOONGSON_HT1_* are configuration
registers of HT1 controller.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongliang Tao <taohl@lemote.com>
Signed-off-by: Hua Yan <yanh@lemote.com>
---
 arch/mips/include/asm/mach-loongson/irq.h      |   26 ++++++
 arch/mips/include/asm/mach-loongson/loongson.h |   10 ++
 arch/mips/loongson/Makefile                    |    6 ++
 arch/mips/loongson/loongson-3/Makefile         |    4 +
 arch/mips/loongson/loongson-3/irq.c            |  110 ++++++++++++++++++++++++
 5 files changed, 156 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-loongson/irq.h
 create mode 100644 arch/mips/loongson/loongson-3/Makefile
 create mode 100644 arch/mips/loongson/loongson-3/irq.c

diff --git a/arch/mips/include/asm/mach-loongson/irq.h b/arch/mips/include/asm/mach-loongson/irq.h
new file mode 100644
index 0000000..5711e3b
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/irq.h
@@ -0,0 +1,26 @@
+#ifndef __ASM_MACH_LOONGSON_IRQ_H_
+#define __ASM_MACH_LOONGSON_IRQ_H_
+
+#include <boot_param.h>
+
+/* cpu core interrupt numbers */
+#define MIPS_CPU_IRQ_BASE 56
+
+#ifdef CONFIG_CPU_LOONGSON3
+
+#define LOONGSON_UART_IRQ   (MIPS_CPU_IRQ_BASE + 2) /* UART */
+#define LOONGSON_HT1_IRQ    (MIPS_CPU_IRQ_BASE + 3) /* HT1 */
+#define LOONGSON_TIMER_IRQ  (MIPS_CPU_IRQ_BASE + 7) /* CPU Timer */
+
+#define LOONGSON_HT1_CFG_BASE		loongson_sysconf.ht_control_base
+#define LOONGSON_HT1_INT_VECTOR_BASE	(LOONGSON_HT1_CFG_BASE + 0x80)
+#define LOONGSON_HT1_INT_EN_BASE	(LOONGSON_HT1_CFG_BASE + 0xa0)
+#define LOONGSON_HT1_INT_VECTOR(n)	\
+		LOONGSON3_REG32(LOONGSON_HT1_INT_VECTOR_BASE, 4 * n)
+#define LOONGSON_HT1_INTN_EN(n)		\
+		LOONGSON3_REG32(LOONGSON_HT1_INT_EN_BASE, 4 * n)
+
+#endif
+
+#include_next <irq.h>
+#endif /* __ASM_MACH_LOONGSON_IRQ_H_ */
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index f0367ff..69e9d9e 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -62,6 +62,12 @@ extern int mach_i8259_irq(void);
 #define LOONGSON_REG(x) \
 	(*(volatile u32 *)((char *)CKSEG1ADDR(LOONGSON_REG_BASE) + (x)))
 
+#define LOONGSON3_REG8(base, x) \
+	(*(volatile u8 *)((char *)TO_UNCAC(base) + (x)))
+
+#define LOONGSON3_REG32(base, x) \
+	(*(volatile u32 *)((char *)TO_UNCAC(base) + (x)))
+
 #define LOONGSON_IRQ_BASE	32
 #define LOONGSON2_PERFCNT_IRQ	(MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */
 
@@ -87,6 +93,10 @@ static inline void do_perfcnt_IRQ(void)
 #define LOONGSON_REG_BASE	0x1fe00000
 #define LOONGSON_REG_SIZE	0x00100000	/* 256Bytes + 256Bytes + ??? */
 #define LOONGSON_REG_TOP	(LOONGSON_REG_BASE+LOONGSON_REG_SIZE-1)
+/* Loongson-3 specific registers */
+#define LOONGSON3_REG_BASE	0x3ff00000
+#define LOONGSON3_REG_SIZE	0x00100000	/* 256Bytes + 256Bytes + ??? */
+#define LOONGSON3_REG_TOP	(LOONGSON3_REG_BASE+LOONGSON3_REG_SIZE-1)
 
 #define LOONGSON_LIO1_BASE	0x1ff00000
 #define LOONGSON_LIO1_SIZE	0x00100000	/* 1M */
diff --git a/arch/mips/loongson/Makefile b/arch/mips/loongson/Makefile
index 0dc0055..7429994 100644
--- a/arch/mips/loongson/Makefile
+++ b/arch/mips/loongson/Makefile
@@ -15,3 +15,9 @@ obj-$(CONFIG_LEMOTE_FULOONG2E)	+= fuloong-2e/
 #
 
 obj-$(CONFIG_LEMOTE_MACH2F)  += lemote-2f/
+
+#
+# All Loongson-3 family machines
+#
+
+obj-$(CONFIG_CPU_LOONGSON3)  += loongson-3/
diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
new file mode 100644
index 0000000..b9968cd
--- /dev/null
+++ b/arch/mips/loongson/loongson-3/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for Loongson-3 family machines
+#
+obj-y			+= irq.o
diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
new file mode 100644
index 0000000..3b52d56
--- /dev/null
+++ b/arch/mips/loongson/loongson-3/irq.c
@@ -0,0 +1,110 @@
+#include <loongson.h>
+#include <irq.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/i8259.h>
+#include <asm/mipsregs.h>
+
+#define LOONGSON_INT_ROUTER_OFFSET	0x1400
+#define LOONGSON_INT_ROUTER_INTEN	\
+	  LOONGSON3_REG32(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + 0x24)
+#define LOONGSON_INT_ROUTER_INTENSET	\
+	  LOONGSON3_REG32(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + 0x28)
+#define LOONGSON_INT_ROUTER_INTENCLR	\
+	  LOONGSON3_REG32(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + 0x2c)
+#define LOONGSON_INT_ROUTER_ENTRY(n)	\
+	  LOONGSON3_REG8(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + n)
+#define LOONGSON_INT_ROUTER_LPC		LOONGSON_INT_ROUTER_ENTRY(0x0a)
+#define LOONGSON_INT_ROUTER_HT1(n)	LOONGSON_INT_ROUTER_ENTRY(n + 0x18)
+
+#define LOONGSON_INT_CORE0_INT0		0x11 /* route to int 0 of core 0 */
+#define LOONGSON_INT_CORE0_INT1		0x21 /* route to int 1 of core 0 */
+
+static void ht_irqdispatch(void)
+{
+	unsigned int i, irq;
+	unsigned int ht_irq[] = {1, 3, 4, 5, 6, 7, 8, 12, 14, 15};
+
+	irq = LOONGSON_HT1_INT_VECTOR(0);
+	LOONGSON_HT1_INT_VECTOR(0) = irq; /* Acknowledge the IRQs */
+
+	for (i = 0; i < (sizeof(ht_irq) / sizeof(*ht_irq)); i++) {
+		if (irq & (0x1 << ht_irq[i]))
+			do_IRQ(ht_irq[i]);
+	}
+}
+
+void mach_irq_dispatch(unsigned int pending)
+{
+	if (pending & CAUSEF_IP7)
+		do_IRQ(LOONGSON_TIMER_IRQ);
+	else if (pending & CAUSEF_IP3)
+		ht_irqdispatch();
+	else if (pending & CAUSEF_IP2)
+		do_IRQ(LOONGSON_UART_IRQ);
+	else {
+		pr_err("%s : spurious interrupt\n", __func__);
+		spurious_interrupt();
+	}
+}
+
+static struct irqaction cascade_irqaction = {
+	.handler = no_action,
+	.name = "cascade",
+};
+
+static inline void mask_loongson_irq(struct irq_data *d)
+{
+	clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
+	irq_disable_hazard();
+}
+
+static inline void unmask_loongson_irq(struct irq_data *d)
+{
+	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
+	irq_enable_hazard();
+}
+
+ /* For MIPS IRQs which shared by all cores */
+static struct irq_chip loongson_irq_chip = {
+	.name		= "Loongson",
+	.irq_ack	= mask_loongson_irq,
+	.irq_mask	= mask_loongson_irq,
+	.irq_mask_ack	= mask_loongson_irq,
+	.irq_unmask	= unmask_loongson_irq,
+	.irq_eoi	= unmask_loongson_irq,
+};
+
+void irq_router_init(void)
+{
+	int i;
+
+	/* route LPC int to cpu core0 int 0 */
+	LOONGSON_INT_ROUTER_LPC = LOONGSON_INT_CORE0_INT0;
+	/* route HT1 int0 ~ int7 to cpu core0 INT1*/
+	for (i = 0; i < 8; i++)
+		LOONGSON_INT_ROUTER_HT1(i) = LOONGSON_INT_CORE0_INT1;
+	/* enable HT1 interrupt */
+	LOONGSON_HT1_INTN_EN(0) = 0xffffffff;
+	/* enable router interrupt intenset */
+	LOONGSON_INT_ROUTER_INTENSET =
+		LOONGSON_INT_ROUTER_INTEN | (0xffff << 16) | 0x1 << 10;
+}
+
+void __init mach_init_irq(void)
+{
+	clear_c0_status(ST0_IM | ST0_BEV);
+
+	irq_router_init();
+	mips_cpu_irq_init();
+	init_i8259_irqs();
+	irq_set_chip_and_handler(LOONGSON_UART_IRQ,
+			&loongson_irq_chip, handle_level_irq);
+
+	/* setup HT1 irq */
+	setup_irq(LOONGSON_HT1_IRQ, &cascade_irqaction);
+
+	set_c0_status(STATUSF_IP2 | STATUSF_IP6);
+}
-- 
1.7.7.3

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

* [PATCH V16 07/12] MIPS: Loongson 3: Add serial port support
  2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
                   ` (5 preceding siblings ...)
  2014-01-08  2:44 ` [PATCH V16 06/12] MIPS: Loongson 3: Add IRQ init and dispatch support Huacai Chen
@ 2014-01-08  2:44 ` Huacai Chen
  2014-01-08 22:58   ` Aurelien Jarno
  2014-01-08  2:44 ` [PATCH V16 08/12] MIPS: Loongson: Add swiotlb to support big memory (>4GB) Huacai Chen
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 55+ messages in thread
From: Huacai Chen @ 2014-01-08  2:44 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: John Crispin, Steven J. Hill, Aurelien Jarno, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Huacai Chen, Hongliang Tao, Hua Yan

Loongson family machines has three types of serial port: PCI UART, LPC
UART and CPU internal UART. Loongson-2E and parts of Loongson-2F based
machines use PCI UART; most Loongson-2F based machines use LPC UART;
Loongson-2G/3A has both LPC and CPU UART but usually use CPU UART.

Port address of UARTs:
CPU UART: REG_BASE + OFFSET;
LPC UART: LIO1_BASE + OFFSET;
PCI UART: PCIIO_BASE + OFFSET.

Since LPC UART are linked in "Local Bus", both CPU UART and LPC UART
are called "CPU provided serial port".

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongliang Tao <taohl@lemote.com>
Signed-off-by: Hua Yan <yanh@lemote.com>
---
 arch/mips/loongson/common/serial.c    |   26 +++++++++++++++-----------
 arch/mips/loongson/common/uart_base.c |    9 ++++++++-
 2 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/arch/mips/loongson/common/serial.c b/arch/mips/loongson/common/serial.c
index 5f2b78a..bd2b709 100644
--- a/arch/mips/loongson/common/serial.c
+++ b/arch/mips/loongson/common/serial.c
@@ -19,19 +19,19 @@
 #include <loongson.h>
 #include <machine.h>
 
-#define PORT(int)			\
+#define PORT(int, clk)			\
 {								\
 	.irq		= int,					\
-	.uartclk	= 1843200,				\
+	.uartclk	= clk,					\
 	.iotype		= UPIO_PORT,				\
 	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,	\
 	.regshift	= 0,					\
 }
 
-#define PORT_M(int)				\
+#define PORT_M(int, clk)				\
 {								\
 	.irq		= MIPS_CPU_IRQ_BASE + (int),		\
-	.uartclk	= 3686400,				\
+	.uartclk	= clk,					\
 	.iotype		= UPIO_MEM,				\
 	.membase	= (void __iomem *)NULL,			\
 	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,	\
@@ -40,13 +40,17 @@
 
 static struct plat_serial8250_port uart8250_data[][2] = {
 	[MACH_LOONGSON_UNKNOWN]		{},
-	[MACH_LEMOTE_FL2E]		{PORT(4), {} },
-	[MACH_LEMOTE_FL2F]		{PORT(3), {} },
-	[MACH_LEMOTE_ML2F7]		{PORT_M(3), {} },
-	[MACH_LEMOTE_YL2F89]		{PORT_M(3), {} },
-	[MACH_DEXXON_GDIUM2F10]		{PORT_M(3), {} },
-	[MACH_LEMOTE_NAS]		{PORT_M(3), {} },
-	[MACH_LEMOTE_LL2F]		{PORT(3), {} },
+	[MACH_LEMOTE_FL2E]              {PORT(4, 1843200), {} },
+	[MACH_LEMOTE_FL2F]              {PORT(3, 1843200), {} },
+	[MACH_LEMOTE_ML2F7]             {PORT_M(3, 3686400), {} },
+	[MACH_LEMOTE_YL2F89]            {PORT_M(3, 3686400), {} },
+	[MACH_DEXXON_GDIUM2F10]         {PORT_M(3, 3686400), {} },
+	[MACH_LEMOTE_NAS]               {PORT_M(3, 3686400), {} },
+	[MACH_LEMOTE_LL2F]              {PORT(3, 1843200), {} },
+	[MACH_LEMOTE_A1004]             {PORT_M(2, 33177600), {} },
+	[MACH_LEMOTE_A1101]             {PORT_M(2, 25000000), {} },
+	[MACH_LEMOTE_A1201]             {PORT_M(2, 25000000), {} },
+	[MACH_LEMOTE_A1205]             {PORT_M(2, 25000000), {} },
 	[MACH_LOONGSON_END]		{},
 };
 
diff --git a/arch/mips/loongson/common/uart_base.c b/arch/mips/loongson/common/uart_base.c
index e192ad0..1e1eeea 100644
--- a/arch/mips/loongson/common/uart_base.c
+++ b/arch/mips/loongson/common/uart_base.c
@@ -35,9 +35,16 @@ void prom_init_loongson_uart_base(void)
 	case MACH_DEXXON_GDIUM2F10:
 	case MACH_LEMOTE_NAS:
 	default:
-		/* The CPU provided serial port */
+		/* The CPU provided serial port (LPC) */
 		loongson_uart_base = LOONGSON_LIO1_BASE + 0x3f8;
 		break;
+	case MACH_LEMOTE_A1004:
+	case MACH_LEMOTE_A1101:
+	case MACH_LEMOTE_A1201:
+	case MACH_LEMOTE_A1205:
+		/* The CPU provided serial port (CPU) */
+		loongson_uart_base = LOONGSON_REG_BASE + 0x1e0;
+		break;
 	}
 
 	_loongson_uart_base =
-- 
1.7.7.3

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

* [PATCH V16 08/12] MIPS: Loongson: Add swiotlb to support big memory (>4GB)
  2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
                   ` (6 preceding siblings ...)
  2014-01-08  2:44 ` [PATCH V16 07/12] MIPS: Loongson 3: Add serial port support Huacai Chen
@ 2014-01-08  2:44 ` Huacai Chen
  2014-01-08 22:58   ` Aurelien Jarno
  2014-01-09 12:56     ` Alex Smith
  2014-01-08  2:44 ` [PATCH V16 09/12] MIPS: Loongson: Add Loongson-3 Kconfig options Huacai Chen
                   ` (5 subsequent siblings)
  13 siblings, 2 replies; 55+ messages in thread
From: Huacai Chen @ 2014-01-08  2:44 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: John Crispin, Steven J. Hill, Aurelien Jarno, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Huacai Chen, Hongliang Tao, Hua Yan

This is probably a workaround because Loongson doesn't support DMA
address above 4GB. If memory is more than 4GB, CONFIG_SWIOTLB and
ZONE_DMA32 should be selected. In this way, DMA pages are allocated
below 4GB preferably.

However, CONFIG_SWIOTLB+ZONE_DMA32 is not enough, so, we provide a
platform-specific dma_map_ops::set_dma_mask() to make sure each
driver's dma_mask and coherent_dma_mask is below 32-bit.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongliang Tao <taohl@lemote.com>
Signed-off-by: Hua Yan <yanh@lemote.com>
---
 arch/mips/include/asm/dma-mapping.h                |    5 +
 .../mips/include/asm/mach-loongson/dma-coherence.h |   22 +++-
 arch/mips/loongson/common/Makefile                 |    5 +
 arch/mips/loongson/common/dma-swiotlb.c            |  165 ++++++++++++++++++++
 4 files changed, 196 insertions(+), 1 deletions(-)
 create mode 100644 arch/mips/loongson/common/dma-swiotlb.c

diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
index 84238c5..06412aa 100644
--- a/arch/mips/include/asm/dma-mapping.h
+++ b/arch/mips/include/asm/dma-mapping.h
@@ -49,9 +49,14 @@ static inline int dma_mapping_error(struct device *dev, u64 mask)
 static inline int
 dma_set_mask(struct device *dev, u64 mask)
 {
+	struct dma_map_ops *ops = get_dma_ops(dev);
+
 	if(!dev->dma_mask || !dma_supported(dev, mask))
 		return -EIO;
 
+	if (ops->set_dma_mask)
+		return ops->set_dma_mask(dev, mask);
+
 	*dev->dma_mask = mask;
 
 	return 0;
diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
index aeb2c05..6a90275 100644
--- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
+++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
@@ -11,24 +11,40 @@
 #ifndef __ASM_MACH_LOONGSON_DMA_COHERENCE_H
 #define __ASM_MACH_LOONGSON_DMA_COHERENCE_H
 
+#ifdef CONFIG_SWIOTLB
+#include <linux/swiotlb.h>
+#endif
+
 struct device;
 
+extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
+extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
 static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
 					  size_t size)
 {
+#ifdef CONFIG_CPU_LOONGSON3
+	return virt_to_phys(addr);
+#else
 	return virt_to_phys(addr) | 0x80000000;
+#endif
 }
 
 static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
 					       struct page *page)
 {
+#ifdef CONFIG_CPU_LOONGSON3
+	return page_to_phys(page);
+#else
 	return page_to_phys(page) | 0x80000000;
+#endif
 }
 
 static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
 	dma_addr_t dma_addr)
 {
-#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
+#if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT)
+	return dma_addr;
+#elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
 	return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff);
 #else
 	return dma_addr & 0x7fffffff;
@@ -55,7 +71,11 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
 
 static inline int plat_device_is_coherent(struct device *dev)
 {
+#ifdef CONFIG_DMA_NONCOHERENT
 	return 0;
+#else
+	return 1;
+#endif /* CONFIG_DMA_NONCOHERENT */
 }
 
 #endif /* __ASM_MACH_LOONGSON_DMA_COHERENCE_H */
diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile
index 9e4484c..0bb9cc9 100644
--- a/arch/mips/loongson/common/Makefile
+++ b/arch/mips/loongson/common/Makefile
@@ -26,3 +26,8 @@ obj-$(CONFIG_CS5536) += cs5536/
 #
 
 obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
+
+#
+# Big Memory (SWIOTLB) Support
+#
+obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o
diff --git a/arch/mips/loongson/common/dma-swiotlb.c b/arch/mips/loongson/common/dma-swiotlb.c
new file mode 100644
index 0000000..9d5451b
--- /dev/null
+++ b/arch/mips/loongson/common/dma-swiotlb.c
@@ -0,0 +1,165 @@
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/swiotlb.h>
+#include <linux/bootmem.h>
+
+#include <asm/bootinfo.h>
+#include <dma-coherence.h>
+
+static void *loongson_dma_alloc_coherent(struct device *dev, size_t size,
+		dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
+{
+	void *ret;
+
+	if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
+		return ret;
+
+	/* ignore region specifiers */
+	gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
+
+#ifdef CONFIG_ISA
+	if (dev == NULL)
+		gfp |= __GFP_DMA;
+	else
+#endif
+#ifdef CONFIG_ZONE_DMA
+	if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
+		gfp |= __GFP_DMA;
+	else
+#endif
+#ifdef CONFIG_ZONE_DMA32
+	 /* Loongson-3 only support DMA in the memory below 4GB now */
+	if (dev->coherent_dma_mask < DMA_BIT_MASK(40))
+		gfp |= __GFP_DMA32;
+	else
+#endif
+	;
+	gfp |= __GFP_NORETRY;
+
+	ret = swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
+	mb();
+	return ret;
+}
+
+static void loongson_dma_free_coherent(struct device *dev, size_t size,
+		void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs)
+{
+	int order = get_order(size);
+
+	if (dma_release_from_coherent(dev, order, vaddr))
+		return;
+
+	swiotlb_free_coherent(dev, size, vaddr, dma_handle);
+}
+
+static dma_addr_t loongson_dma_map_page(struct device *dev, struct page *page,
+				unsigned long offset, size_t size,
+				enum dma_data_direction dir,
+				struct dma_attrs *attrs)
+{
+	dma_addr_t daddr = swiotlb_map_page(dev, page, offset, size,
+					dir, attrs);
+	mb();
+	return daddr;
+}
+
+static int loongson_dma_map_sg(struct device *dev, struct scatterlist *sg,
+				int nents, enum dma_data_direction dir,
+				struct dma_attrs *attrs)
+{
+	int r = swiotlb_map_sg_attrs(dev, sg, nents, dir, NULL);
+	mb();
+
+	return r;
+}
+
+static void loongson_dma_sync_single_for_device(struct device *dev,
+				dma_addr_t dma_handle, size_t size,
+				enum dma_data_direction dir)
+{
+	swiotlb_sync_single_for_device(dev, dma_handle, size, dir);
+	mb();
+}
+
+static void loongson_dma_sync_sg_for_device(struct device *dev,
+				struct scatterlist *sg, int nents,
+				enum dma_data_direction dir)
+{
+	swiotlb_sync_sg_for_device(dev, sg, nents, dir);
+	mb();
+}
+
+static dma_addr_t
+loongson_unity_phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	return paddr;
+}
+
+static phys_addr_t
+loongson_unity_dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+	return daddr;
+}
+
+struct loongson_dma_map_ops {
+	struct dma_map_ops dma_map_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);
+};
+
+dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	struct loongson_dma_map_ops *ops = container_of(get_dma_ops(dev),
+				struct loongson_dma_map_ops, dma_map_ops);
+
+	return ops->phys_to_dma(dev, paddr);
+}
+
+phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+	struct loongson_dma_map_ops *ops = container_of(get_dma_ops(dev),
+				struct loongson_dma_map_ops, dma_map_ops);
+
+	return ops->dma_to_phys(dev, daddr);
+}
+
+static int loongson_dma_set_mask(struct device *dev, u64 mask)
+{
+	/* Loongson doesn't support DMA above 32-bit */
+	if (mask > DMA_BIT_MASK(32)) {
+		*dev->dma_mask = DMA_BIT_MASK(32);
+		return -EIO;
+	}
+
+	*dev->dma_mask = mask;
+
+	return 0;
+}
+
+static struct loongson_dma_map_ops loongson_linear_dma_map_ops = {
+	.dma_map_ops = {
+		.alloc = loongson_dma_alloc_coherent,
+		.free = loongson_dma_free_coherent,
+		.map_page = loongson_dma_map_page,
+		.unmap_page = swiotlb_unmap_page,
+		.map_sg = loongson_dma_map_sg,
+		.unmap_sg = swiotlb_unmap_sg_attrs,
+		.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
+		.sync_single_for_device = loongson_dma_sync_single_for_device,
+		.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+		.sync_sg_for_device = loongson_dma_sync_sg_for_device,
+		.mapping_error = swiotlb_dma_mapping_error,
+		.dma_supported = swiotlb_dma_supported,
+		.set_dma_mask = loongson_dma_set_mask
+	},
+	.phys_to_dma = loongson_unity_phys_to_dma,
+	.dma_to_phys = loongson_unity_dma_to_phys
+};
+
+void __init plat_swiotlb_setup(void)
+{
+	swiotlb_init(1);
+	mips_dma_map_ops = &loongson_linear_dma_map_ops.dma_map_ops;
+}
-- 
1.7.7.3

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

* [PATCH V16 09/12] MIPS: Loongson: Add Loongson-3 Kconfig options
  2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
                   ` (7 preceding siblings ...)
  2014-01-08  2:44 ` [PATCH V16 08/12] MIPS: Loongson: Add swiotlb to support big memory (>4GB) Huacai Chen
@ 2014-01-08  2:44 ` Huacai Chen
  2014-01-09 13:07     ` Alex Smith
  2014-01-08  2:44 ` [PATCH V16 10/12] MIPS: Loongson 3: Add Loongson-3 SMP support Huacai Chen
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 55+ messages in thread
From: Huacai Chen @ 2014-01-08  2:44 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: John Crispin, Steven J. Hill, Aurelien Jarno, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Huacai Chen, Hongliang Tao, Hua Yan

Added Kconfig options include: Loongson-3 CPU and machine definition,
CPU cache features, UEFI-like firmware interface (LEFI), HT-linked PCI,
and big memory support.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongliang Tao <taohl@lemote.com>
Signed-off-by: Hua Yan <yanh@lemote.com>
---
 arch/mips/Kconfig           |   29 +++++++++++++++++++++++++++-
 arch/mips/loongson/Kconfig  |   44 +++++++++++++++++++++++++++++++++++++++++++
 arch/mips/loongson/Platform |    1 +
 3 files changed, 73 insertions(+), 1 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 17cc7ff..513e941 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1487,6 +1487,18 @@ config CPU_LOONGSON2
 	select CPU_SUPPORTS_HIGHMEM
 	select CPU_SUPPORTS_HUGEPAGES
 
+config CPU_LOONGSON3
+	bool "Loongson 3 CPU"
+	depends on SYS_HAS_CPU_LOONGSON3
+	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HIGHMEM
+	select CPU_SUPPORTS_HUGEPAGES
+	select WEAK_ORDERING
+	select WEAK_REORDERING_BEYOND_LLSC
+	help
+		The Loongson 3 processor implements the MIPS III instruction set
+		with many extensions.
+
 config CPU_LOONGSON1
 	bool
 	select CPU_MIPS32
@@ -1513,6 +1526,10 @@ config SYS_HAS_CPU_LOONGSON2F
 	select CPU_SUPPORTS_ADDRWINCFG if 64BIT
 	select CPU_SUPPORTS_UNCACHED_ACCELERATED
 
+config SYS_HAS_CPU_LOONGSON3
+	bool
+	select CPU_SUPPORTS_CPUFREQ
+
 config SYS_HAS_CPU_LOONGSON1B
 	bool
 
@@ -1703,7 +1720,7 @@ choice
 
 config PAGE_SIZE_4KB
 	bool "4kB"
-	depends on !CPU_LOONGSON2
+	depends on !CPU_LOONGSON2 && !CPU_LOONGSON3
 	help
 	 This option select the standard 4kB Linux page size.  On some
 	 R3000-family processors this is the only available page size.  Using
@@ -2373,6 +2390,16 @@ config PCI
 	  your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
 	  say Y, otherwise N.
 
+config HT_PCI
+	bool "Support for HT-linked PCI"
+	depends on CPU_LOONGSON3
+	select PCI_DOMAINS
+	help
+	  Loongson family machines use Hyper-Transport bus for inter-core
+	  connection and device connection. The PCI bus is a subordinate
+	  linked at HT. Choose Y unless you are using Loongson 2E/2F based
+	  machines.
+
 config PCI_DOMAINS
 	bool
 
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
index 263beb9..4f3967c 100644
--- a/arch/mips/loongson/Kconfig
+++ b/arch/mips/loongson/Kconfig
@@ -59,6 +59,33 @@ config LEMOTE_MACH2F
 
 	  These family machines include fuloong2f mini PC, yeeloong2f notebook,
 	  LingLoong allinone PC and so forth.
+
+config LEMOTE_MACH3A
+	bool "Lemote Loongson 3A family machines"
+	select ARCH_SPARSEMEM_ENABLE
+	select GENERIC_ISA_DMA_SUPPORT_BROKEN
+	select GENERIC_HARDIRQS_NO__DO_IRQ
+	select BOOT_ELF32
+	select BOARD_SCACHE
+	select CSRC_R4K
+	select CEVT_R4K
+	select CPU_HAS_WB
+	select HW_HAS_PCI
+	select ISA
+	select I8259
+	select IRQ_CPU
+	select SYS_HAS_CPU_LOONGSON3
+	select SYS_HAS_EARLY_PRINTK
+	select SYS_SUPPORTS_SMP
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_HIGHMEM
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select LOONGSON_MC146818
+	select ZONE_DMA32 if 64BIT
+	select LEFI_FIRMWARE_INTERFACE
+	help
+		Lemote Loongson 3A family machines utilize the 3A revision of
+		Loongson processor and RS780/SBX00 chipset.
 endchoice
 
 config CS5536
@@ -86,8 +114,24 @@ config LOONGSON_UART_BASE
 	default y
 	depends on EARLY_PRINTK || SERIAL_8250
 
+config IOMMU_HELPER
+	bool
+
+config NEED_SG_DMA_LENGTH
+	bool
+
+config SWIOTLB
+	bool "Soft IOMMU Support for Big Memory (>4GB)"
+	depends on CPU_LOONGSON3
+	select IOMMU_HELPER
+	select NEED_SG_DMA_LENGTH
+	select NEED_DMA_MAP_STATE
+
 config LOONGSON_MC146818
 	bool
 	default n
 
+config LEFI_FIRMWARE_INTERFACE
+	bool
+
 endif # MACH_LOONGSON
diff --git a/arch/mips/loongson/Platform b/arch/mips/loongson/Platform
index 29692e5..6205372 100644
--- a/arch/mips/loongson/Platform
+++ b/arch/mips/loongson/Platform
@@ -30,3 +30,4 @@ platform-$(CONFIG_MACH_LOONGSON) += loongson/
 cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely
 load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000
 load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000
+load-$(CONFIG_CPU_LOONGSON3) += 0xffffffff80200000
-- 
1.7.7.3

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

* [PATCH V16 10/12] MIPS: Loongson 3: Add Loongson-3 SMP support
  2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
                   ` (8 preceding siblings ...)
  2014-01-08  2:44 ` [PATCH V16 09/12] MIPS: Loongson: Add Loongson-3 Kconfig options Huacai Chen
@ 2014-01-08  2:44 ` Huacai Chen
  2014-01-09 13:19     ` Alex Smith
  2014-01-08  2:44 ` [PATCH V16 11/12] MIPS: Loongson 3: Add CPU hotplug support Huacai Chen
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 55+ messages in thread
From: Huacai Chen @ 2014-01-08  2:44 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: John Crispin, Steven J. Hill, Aurelien Jarno, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Huacai Chen, Hongliang Tao, Hua Yan

IPI registers of Loongson-3 include IPI_SET, IPI_CLEAR, IPI_STATUS,
IPI_EN and IPI_MAILBOX_BUF. Each bit of IPI_STATUS indicate a type of
IPI and IPI_EN indicate whether the IPI is enabled. The sender write 1
to IPI_SET bits generate IPIs in IPI_STATUS, and receiver write 1 to
bits of IPI_CLEAR to clear IPIs. IPI_MAILBOX_BUF are used to deliver
more information about IPIs.

Why we change code in arch/mips/loongson/common/setup.c?

If without this change, when SMP configured, system cannot boot since
it hang at printk() in cgroup_init_early(). The root cause is:

console_trylock()
  \-->down_trylock(&console_sem)
    \-->raw_spin_unlock_irqrestore(&sem->lock, flags)
      \-->_raw_spin_unlock_irqrestore()(SMP/UP have different versions)
        \-->__raw_spin_unlock_irqrestore()  (following is the SMP case)
          \-->do_raw_spin_unlock()
            \-->arch_spin_unlock()
              \-->nudge_writes()
                \-->mb()
                  \-->wbflush()
                    \-->__wbflush()

In previous code __wbflush() is initialized in plat_mem_setup(), but
cgroup_init_early() is called before plat_mem_setup(). Therefore, In
this patch we make changes to avoid boot failure.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongliang Tao <taohl@lemote.com>
Signed-off-by: Hua Yan <yanh@lemote.com>
---
 arch/mips/include/asm/mach-loongson/irq.h      |    2 +
 arch/mips/include/asm/mach-loongson/loongson.h |    1 +
 arch/mips/loongson/common/init.c               |    3 +
 arch/mips/loongson/common/setup.c              |    8 +-
 arch/mips/loongson/loongson-3/Makefile         |    2 +
 arch/mips/loongson/loongson-3/irq.c            |   20 ++
 arch/mips/loongson/loongson-3/smp.c            |  279 ++++++++++++++++++++++++
 arch/mips/loongson/loongson-3/smp.h            |   24 ++
 8 files changed, 334 insertions(+), 5 deletions(-)
 create mode 100644 arch/mips/loongson/loongson-3/smp.c
 create mode 100644 arch/mips/loongson/loongson-3/smp.h

diff --git a/arch/mips/include/asm/mach-loongson/irq.h b/arch/mips/include/asm/mach-loongson/irq.h
index 5711e3b..d2f0e2a 100644
--- a/arch/mips/include/asm/mach-loongson/irq.h
+++ b/arch/mips/include/asm/mach-loongson/irq.h
@@ -22,5 +22,7 @@
 
 #endif
 
+extern void loongson3_ipi_interrupt(struct pt_regs *regs);
+
 #include_next <irq.h>
 #endif /* __ASM_MACH_LOONGSON_IRQ_H_ */
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index 69e9d9e..f185907 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -27,6 +27,7 @@ extern void mach_prepare_shutdown(void);
 /* environment arguments from bootloader */
 extern u32 cpu_clock_freq;
 extern u32 memsize, highmemsize;
+extern struct plat_smp_ops loongson3_smp_ops;
 
 /* loongson-specific command line, env and memory initialization */
 extern void __init prom_init_memory(void);
diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
index 81ba3b4..a7c521b 100644
--- a/arch/mips/loongson/common/init.c
+++ b/arch/mips/loongson/common/init.c
@@ -33,6 +33,9 @@ void __init prom_init(void)
 
 	/*init the uart base address */
 	prom_init_uart_base();
+#if defined(CONFIG_SMP)
+	register_smp_ops(&loongson3_smp_ops);
+#endif
 }
 
 void __init prom_free_prom_memory(void)
diff --git a/arch/mips/loongson/common/setup.c b/arch/mips/loongson/common/setup.c
index 8223f8a..bb4ac92 100644
--- a/arch/mips/loongson/common/setup.c
+++ b/arch/mips/loongson/common/setup.c
@@ -18,9 +18,6 @@
 #include <linux/screen_info.h>
 #endif
 
-void (*__wbflush)(void);
-EXPORT_SYMBOL(__wbflush);
-
 static void wbflush_loongson(void)
 {
 	asm(".set\tpush\n\t"
@@ -32,10 +29,11 @@ static void wbflush_loongson(void)
 	    ".set mips0\n\t");
 }
 
+void (*__wbflush)(void) = wbflush_loongson;
+EXPORT_SYMBOL(__wbflush);
+
 void __init plat_mem_setup(void)
 {
-	__wbflush = wbflush_loongson;
-
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
 	conswitchp = &vga_con;
diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
index b9968cd..70152b2 100644
--- a/arch/mips/loongson/loongson-3/Makefile
+++ b/arch/mips/loongson/loongson-3/Makefile
@@ -2,3 +2,5 @@
 # Makefile for Loongson-3 family machines
 #
 obj-y			+= irq.o
+
+obj-$(CONFIG_SMP)	+= smp.o
diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
index 3b52d56..d8920a8 100644
--- a/arch/mips/loongson/loongson-3/irq.c
+++ b/arch/mips/loongson/loongson-3/irq.c
@@ -40,6 +40,10 @@ void mach_irq_dispatch(unsigned int pending)
 {
 	if (pending & CAUSEF_IP7)
 		do_IRQ(LOONGSON_TIMER_IRQ);
+#if defined(CONFIG_SMP)
+	else if (pending & CAUSEF_IP6)
+		loongson3_ipi_interrupt(NULL);
+#endif
 	else if (pending & CAUSEF_IP3)
 		ht_irqdispatch();
 	else if (pending & CAUSEF_IP2)
@@ -59,10 +63,26 @@ static inline void mask_loongson_irq(struct irq_data *d)
 {
 	clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
 	irq_disable_hazard();
+
+	/* Workaround: UART IRQ may deliver to any core */
+	if (d->irq == LOONGSON_UART_IRQ) {
+		int cpu = smp_processor_id();
+
+		LOONGSON_INT_ROUTER_INTENCLR = 1 << 10;
+		LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
+	}
 }
 
 static inline void unmask_loongson_irq(struct irq_data *d)
 {
+	/* Workaround: UART IRQ may deliver to any core */
+	if (d->irq == LOONGSON_UART_IRQ) {
+		int cpu = smp_processor_id();
+
+		LOONGSON_INT_ROUTER_INTENSET = 1 << 10;
+		LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
+	}
+
 	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
 	irq_enable_hazard();
 }
diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
new file mode 100644
index 0000000..a264bcb
--- /dev/null
+++ b/arch/mips/loongson/loongson-3/smp.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2010, 2011, 2012, Lemote, Inc.
+ * Author: Chen Huacai, chenhc@lemote.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/cpufreq.h>
+#include <asm/processor.h>
+#include <asm/time.h>
+#include <asm/clock.h>
+#include <asm/tlbflush.h>
+#include <loongson.h>
+
+#include "smp.h"
+
+/* read a 64bit value from ipi register */
+uint64_t loongson3_ipi_read64(void *addr)
+{
+	return readq(addr);
+};
+
+/* write a 64bit value to ipi register */
+void loongson3_ipi_write64(uint64_t action, void *addr)
+{
+	writeq(action, addr);
+	__wbflush();
+};
+
+/* read a 32bit value from ipi register */
+uint32_t loongson3_ipi_read32(void *addr)
+{
+	return readl(addr);
+};
+
+/* write a 32bit value to ipi register */
+void loongson3_ipi_write32(uint32_t action, void *addr)
+{
+	writel(action, addr);
+	__wbflush();
+};
+
+static void *ipi_set0_regs[] = {
+	(void *)(smp_core_group0_base + smp_core0_offset + SET0),
+	(void *)(smp_core_group0_base + smp_core1_offset + SET0),
+	(void *)(smp_core_group0_base + smp_core2_offset + SET0),
+	(void *)(smp_core_group0_base + smp_core3_offset + SET0),
+	(void *)(smp_core_group1_base + smp_core0_offset + SET0),
+	(void *)(smp_core_group1_base + smp_core1_offset + SET0),
+	(void *)(smp_core_group1_base + smp_core2_offset + SET0),
+	(void *)(smp_core_group1_base + smp_core3_offset + SET0),
+	(void *)(smp_core_group2_base + smp_core0_offset + SET0),
+	(void *)(smp_core_group2_base + smp_core1_offset + SET0),
+	(void *)(smp_core_group2_base + smp_core2_offset + SET0),
+	(void *)(smp_core_group2_base + smp_core3_offset + SET0),
+	(void *)(smp_core_group3_base + smp_core0_offset + SET0),
+	(void *)(smp_core_group3_base + smp_core1_offset + SET0),
+	(void *)(smp_core_group3_base + smp_core2_offset + SET0),
+	(void *)(smp_core_group3_base + smp_core3_offset + SET0),
+};
+
+static void *ipi_clear0_regs[] = {
+	(void *)(smp_core_group0_base + smp_core0_offset + CLEAR0),
+	(void *)(smp_core_group0_base + smp_core1_offset + CLEAR0),
+	(void *)(smp_core_group0_base + smp_core2_offset + CLEAR0),
+	(void *)(smp_core_group0_base + smp_core3_offset + CLEAR0),
+	(void *)(smp_core_group1_base + smp_core0_offset + CLEAR0),
+	(void *)(smp_core_group1_base + smp_core1_offset + CLEAR0),
+	(void *)(smp_core_group1_base + smp_core2_offset + CLEAR0),
+	(void *)(smp_core_group1_base + smp_core3_offset + CLEAR0),
+	(void *)(smp_core_group2_base + smp_core0_offset + CLEAR0),
+	(void *)(smp_core_group2_base + smp_core1_offset + CLEAR0),
+	(void *)(smp_core_group2_base + smp_core2_offset + CLEAR0),
+	(void *)(smp_core_group2_base + smp_core3_offset + CLEAR0),
+	(void *)(smp_core_group3_base + smp_core0_offset + CLEAR0),
+	(void *)(smp_core_group3_base + smp_core1_offset + CLEAR0),
+	(void *)(smp_core_group3_base + smp_core2_offset + CLEAR0),
+	(void *)(smp_core_group3_base + smp_core3_offset + CLEAR0),
+};
+
+static void *ipi_status0_regs[] = {
+	(void *)(smp_core_group0_base + smp_core0_offset + STATUS0),
+	(void *)(smp_core_group0_base + smp_core1_offset + STATUS0),
+	(void *)(smp_core_group0_base + smp_core2_offset + STATUS0),
+	(void *)(smp_core_group0_base + smp_core3_offset + STATUS0),
+	(void *)(smp_core_group1_base + smp_core0_offset + STATUS0),
+	(void *)(smp_core_group1_base + smp_core1_offset + STATUS0),
+	(void *)(smp_core_group1_base + smp_core2_offset + STATUS0),
+	(void *)(smp_core_group1_base + smp_core3_offset + STATUS0),
+	(void *)(smp_core_group2_base + smp_core0_offset + STATUS0),
+	(void *)(smp_core_group2_base + smp_core1_offset + STATUS0),
+	(void *)(smp_core_group2_base + smp_core2_offset + STATUS0),
+	(void *)(smp_core_group2_base + smp_core3_offset + STATUS0),
+	(void *)(smp_core_group3_base + smp_core0_offset + STATUS0),
+	(void *)(smp_core_group3_base + smp_core1_offset + STATUS0),
+	(void *)(smp_core_group3_base + smp_core2_offset + STATUS0),
+	(void *)(smp_core_group3_base + smp_core3_offset + STATUS0),
+};
+
+static void *ipi_en0_regs[] = {
+	(void *)(smp_core_group0_base + smp_core0_offset + EN0),
+	(void *)(smp_core_group0_base + smp_core1_offset + EN0),
+	(void *)(smp_core_group0_base + smp_core2_offset + EN0),
+	(void *)(smp_core_group0_base + smp_core3_offset + EN0),
+	(void *)(smp_core_group1_base + smp_core0_offset + EN0),
+	(void *)(smp_core_group1_base + smp_core1_offset + EN0),
+	(void *)(smp_core_group1_base + smp_core2_offset + EN0),
+	(void *)(smp_core_group1_base + smp_core3_offset + EN0),
+	(void *)(smp_core_group2_base + smp_core0_offset + EN0),
+	(void *)(smp_core_group2_base + smp_core1_offset + EN0),
+	(void *)(smp_core_group2_base + smp_core2_offset + EN0),
+	(void *)(smp_core_group2_base + smp_core3_offset + EN0),
+	(void *)(smp_core_group3_base + smp_core0_offset + EN0),
+	(void *)(smp_core_group3_base + smp_core1_offset + EN0),
+	(void *)(smp_core_group3_base + smp_core2_offset + EN0),
+	(void *)(smp_core_group3_base + smp_core3_offset + EN0),
+};
+
+static void *ipi_mailbox_buf[] = {
+	(void *)(smp_core_group0_base + smp_core0_offset + BUF),
+	(void *)(smp_core_group0_base + smp_core1_offset + BUF),
+	(void *)(smp_core_group0_base + smp_core2_offset + BUF),
+	(void *)(smp_core_group0_base + smp_core3_offset + BUF),
+	(void *)(smp_core_group1_base + smp_core0_offset + BUF),
+	(void *)(smp_core_group1_base + smp_core1_offset + BUF),
+	(void *)(smp_core_group1_base + smp_core2_offset + BUF),
+	(void *)(smp_core_group1_base + smp_core3_offset + BUF),
+	(void *)(smp_core_group2_base + smp_core0_offset + BUF),
+	(void *)(smp_core_group2_base + smp_core1_offset + BUF),
+	(void *)(smp_core_group2_base + smp_core2_offset + BUF),
+	(void *)(smp_core_group2_base + smp_core3_offset + BUF),
+	(void *)(smp_core_group3_base + smp_core0_offset + BUF),
+	(void *)(smp_core_group3_base + smp_core1_offset + BUF),
+	(void *)(smp_core_group3_base + smp_core2_offset + BUF),
+	(void *)(smp_core_group3_base + smp_core3_offset + BUF),
+};
+
+/*
+ * Simple enough, just poke the appropriate ipi register
+ */
+static void loongson3_send_ipi_single(int cpu, unsigned int action)
+{
+	loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu]);
+}
+
+static void
+loongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action)
+{
+	unsigned int i;
+
+	for_each_cpu(i, mask)
+		loongson3_ipi_write32((u32)action, ipi_set0_regs[i]);
+}
+
+void loongson3_ipi_interrupt(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+	unsigned int action;
+
+	/* Load the ipi register to figure out what we're supposed to do */
+	action = loongson3_ipi_read32(ipi_status0_regs[cpu]);
+
+	/* Clear the ipi register to clear the interrupt */
+	loongson3_ipi_write32((u32)action, ipi_clear0_regs[cpu]);
+
+	if (action & SMP_RESCHEDULE_YOURSELF)
+		scheduler_ipi();
+
+	if (action & SMP_CALL_FUNCTION)
+		smp_call_function_interrupt();
+}
+
+/*
+ * SMP init and finish on secondary CPUs
+ */
+void loongson3_init_secondary(void)
+{
+	int i;
+	unsigned int imask = STATUSF_IP7 | STATUSF_IP6 |
+			     STATUSF_IP3 | STATUSF_IP2;
+
+	/* Set interrupt mask, but don't enable */
+	change_c0_status(ST0_IM, imask);
+
+	for (i = 0; i < loongson_sysconf.nr_cpus; i++)
+		loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]);
+}
+
+void loongson3_smp_finish(void)
+{
+	write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
+	local_irq_enable();
+	loongson3_ipi_write64(0,
+			(void *)(ipi_mailbox_buf[smp_processor_id()]+0x0));
+	pr_info("CPU#%d finished, CP0_ST=%x\n",
+			smp_processor_id(), read_c0_status());
+}
+
+void __init loongson3_smp_setup(void)
+{
+	int i, num;
+
+	init_cpu_possible(cpu_none_mask);
+	set_cpu_possible(0, true);
+
+	__cpu_number_map[0] = 0;
+	__cpu_logical_map[0] = 0;
+
+	/* For unified kernel, NR_CPUS is the maximum possible value,
+	 * loongson_sysconf.nr_cpus is the really present value */
+	for (i = 1, num = 0; i < loongson_sysconf.nr_cpus; i++) {
+		set_cpu_possible(i, true);
+		__cpu_number_map[i] = ++num;
+		__cpu_logical_map[num] = i;
+	}
+	pr_info("Detected %i available secondary CPU(s)\n", num);
+}
+
+void __init loongson3_prepare_cpus(unsigned int max_cpus)
+{
+}
+
+/*
+ * Setup the PC, SP, and GP of a secondary processor and start it runing!
+ */
+void loongson3_boot_secondary(int cpu, struct task_struct *idle)
+{
+	unsigned long startargs[4];
+
+	pr_info("Booting CPU#%d...\n", cpu);
+
+	/* startargs[] are initial PC, SP and GP for secondary CPU */
+	startargs[0] = (unsigned long)&smp_bootstrap;
+	startargs[1] = (unsigned long)__KSTK_TOS(idle);
+	startargs[2] = (unsigned long)task_thread_info(idle);
+	startargs[3] = 0;
+
+	pr_debug("CPU#%d, func_pc=%lx, sp=%lx, gp=%lx\n",
+			cpu, startargs[0], startargs[1], startargs[2]);
+
+	loongson3_ipi_write64(startargs[3], (void *)(ipi_mailbox_buf[cpu]+0x18));
+	loongson3_ipi_write64(startargs[2], (void *)(ipi_mailbox_buf[cpu]+0x10));
+	loongson3_ipi_write64(startargs[1], (void *)(ipi_mailbox_buf[cpu]+0x8));
+	loongson3_ipi_write64(startargs[0], (void *)(ipi_mailbox_buf[cpu]+0x0));
+}
+
+/*
+ * Final cleanup after all secondaries booted
+ */
+void __init loongson3_cpus_done(void)
+{
+}
+
+struct plat_smp_ops loongson3_smp_ops = {
+	.send_ipi_single = loongson3_send_ipi_single,
+	.send_ipi_mask = loongson3_send_ipi_mask,
+	.init_secondary = loongson3_init_secondary,
+	.smp_finish = loongson3_smp_finish,
+	.cpus_done = loongson3_cpus_done,
+	.boot_secondary = loongson3_boot_secondary,
+	.smp_setup = loongson3_smp_setup,
+	.prepare_cpus = loongson3_prepare_cpus,
+};
diff --git a/arch/mips/loongson/loongson-3/smp.h b/arch/mips/loongson/loongson-3/smp.h
new file mode 100644
index 0000000..dc9ce69
--- /dev/null
+++ b/arch/mips/loongson/loongson-3/smp.h
@@ -0,0 +1,24 @@
+/* for Loongson-3A smp support */
+
+/* 4 groups(nodes) in maximum in numa case */
+#define  smp_core_group0_base    0x900000003ff01000
+#define  smp_core_group1_base    0x900010003ff01000
+#define  smp_core_group2_base    0x900020003ff01000
+#define  smp_core_group3_base    0x900030003ff01000
+
+/* 4 cores in each group(node) */
+#define  smp_core0_offset  0x000
+#define  smp_core1_offset  0x100
+#define  smp_core2_offset  0x200
+#define  smp_core3_offset  0x300
+
+/* ipi registers offsets */
+#define  STATUS0  0x00
+#define  EN0      0x04
+#define  SET0     0x08
+#define  CLEAR0   0x0c
+#define  STATUS1  0x10
+#define  MASK1    0x14
+#define  SET1     0x18
+#define  CLEAR1   0x1c
+#define  BUF      0x20
-- 
1.7.7.3

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

* [PATCH V16 11/12] MIPS: Loongson 3: Add CPU hotplug support
  2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
                   ` (9 preceding siblings ...)
  2014-01-08  2:44 ` [PATCH V16 10/12] MIPS: Loongson 3: Add Loongson-3 SMP support Huacai Chen
@ 2014-01-08  2:44 ` Huacai Chen
  2014-01-11 15:24   ` Aurelien Jarno
  2014-01-08  2:44 ` [PATCH V16 12/12] MIPS: Loongson: Add a Loongson-3 default config file Huacai Chen
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 55+ messages in thread
From: Huacai Chen @ 2014-01-08  2:44 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: John Crispin, Steven J. Hill, Aurelien Jarno, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Huacai Chen, Hongliang Tao, Hua Yan

Tips of Loongson's CPU hotplug:
1, To fully shutdown a core in Loongson 3, the target core should go to
   CKSEG1 and flush all L1 cache entries at first. Then, another core
   (usually Core 0) can safely disable the clock of the target core. So
   play_dead() call loongson3_play_dead() via CKSEG1 (both uncached and
   unmmaped).
2, The default clocksource of Loongson is MIPS. Since clock source is a
   global device, timekeeping need the CP0' Count registers of each core
   be synchronous. Thus, when a core is up, we use a SMP_ASK_C0COUNT IPI
   to ask Core-0's Count.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongliang Tao <taohl@lemote.com>
Signed-off-by: Hua Yan <yanh@lemote.com>
---
 arch/mips/include/asm/mach-loongson/irq.h      |    1 +
 arch/mips/include/asm/mach-loongson/loongson.h |    6 +-
 arch/mips/include/asm/smp.h                    |    1 +
 arch/mips/loongson/Kconfig                     |    1 +
 arch/mips/loongson/loongson-3/irq.c            |   10 ++
 arch/mips/loongson/loongson-3/smp.c            |  171 +++++++++++++++++++++++-
 6 files changed, 185 insertions(+), 5 deletions(-)

diff --git a/arch/mips/include/asm/mach-loongson/irq.h b/arch/mips/include/asm/mach-loongson/irq.h
index d2f0e2a..620b3e9 100644
--- a/arch/mips/include/asm/mach-loongson/irq.h
+++ b/arch/mips/include/asm/mach-loongson/irq.h
@@ -22,6 +22,7 @@
 
 #endif
 
+extern void fixup_irqs(void);
 extern void loongson3_ipi_interrupt(struct pt_regs *regs);
 
 #include_next <irq.h>
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index f185907..f3fd1eb 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -249,6 +249,9 @@ static inline void do_perfcnt_IRQ(void)
 #define LOONGSON_PXARB_CFG		LOONGSON_REG(LOONGSON_REGBASE + 0x68)
 #define LOONGSON_PXARB_STATUS		LOONGSON_REG(LOONGSON_REGBASE + 0x6c)
 
+/* Chip Config */
+#define LOONGSON_CHIPCFG0		LOONGSON_REG(LOONGSON_REGBASE + 0x80)
+
 /* pcimap */
 
 #define LOONGSON_PCIMAP_PCIMAP_LO0	0x0000003f
@@ -264,9 +267,6 @@ static inline void do_perfcnt_IRQ(void)
 #ifdef CONFIG_CPU_SUPPORTS_CPUFREQ
 #include <linux/cpufreq.h>
 extern struct cpufreq_frequency_table loongson2_clockmod_table[];
-
-/* Chip Config */
-#define LOONGSON_CHIPCFG0		LOONGSON_REG(LOONGSON_REGBASE + 0x80)
 #endif
 
 /*
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index eb60087..efa02ac 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -42,6 +42,7 @@ extern int __cpu_logical_map[NR_CPUS];
 #define SMP_ICACHE_FLUSH	0x4
 /* Used by kexec crashdump to save all cpu's state */
 #define SMP_DUMP		0x8
+#define SMP_ASK_C0COUNT		0x10
 
 extern volatile cpumask_t cpu_callin_map;
 
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
index 4f3967c..f29e604 100644
--- a/arch/mips/loongson/Kconfig
+++ b/arch/mips/loongson/Kconfig
@@ -77,6 +77,7 @@ config LEMOTE_MACH3A
 	select SYS_HAS_CPU_LOONGSON3
 	select SYS_HAS_EARLY_PRINTK
 	select SYS_SUPPORTS_SMP
+	select SYS_SUPPORTS_HOTPLUG_CPU
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_HIGHMEM
 	select SYS_SUPPORTS_LITTLE_ENDIAN
diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
index d8920a8..d457366 100644
--- a/arch/mips/loongson/loongson-3/irq.c
+++ b/arch/mips/loongson/loongson-3/irq.c
@@ -128,3 +128,13 @@ void __init mach_init_irq(void)
 
 	set_c0_status(STATUSF_IP2 | STATUSF_IP6);
 }
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+void fixup_irqs(void)
+{
+	irq_cpu_offline();
+	clear_c0_status(ST0_IM);
+}
+
+#endif
diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
index a264bcb..059ef94 100644
--- a/arch/mips/loongson/loongson-3/smp.c
+++ b/arch/mips/loongson/loongson-3/smp.c
@@ -26,10 +26,14 @@
 #include <asm/time.h>
 #include <asm/clock.h>
 #include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
 #include <loongson.h>
 
 #include "smp.h"
 
+DEFINE_PER_CPU(int, cpu_state);
+DEFINE_PER_CPU(uint32_t, core0_c0count);
+
 /* read a 64bit value from ipi register */
 uint64_t loongson3_ipi_read64(void *addr)
 {
@@ -170,8 +174,8 @@ loongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action)
 
 void loongson3_ipi_interrupt(struct pt_regs *regs)
 {
-	int cpu = smp_processor_id();
-	unsigned int action;
+	int i, cpu = smp_processor_id();
+	unsigned int action, c0count;
 
 	/* Load the ipi register to figure out what we're supposed to do */
 	action = loongson3_ipi_read32(ipi_status0_regs[cpu]);
@@ -184,14 +188,24 @@ void loongson3_ipi_interrupt(struct pt_regs *regs)
 
 	if (action & SMP_CALL_FUNCTION)
 		smp_call_function_interrupt();
+
+	if (action & SMP_ASK_C0COUNT) {
+		BUG_ON(cpu != 0);
+		c0count = read_c0_count();
+		for (i = 1; i < loongson_sysconf.nr_cpus; i++)
+			per_cpu(core0_c0count, i) = c0count;
+	}
 }
 
+#define MAX_LOOPS 1000
 /*
  * SMP init and finish on secondary CPUs
  */
 void loongson3_init_secondary(void)
 {
 	int i;
+	uint32_t initcount;
+	unsigned int cpu = smp_processor_id();
 	unsigned int imask = STATUSF_IP7 | STATUSF_IP6 |
 			     STATUSF_IP3 | STATUSF_IP2;
 
@@ -200,6 +214,21 @@ void loongson3_init_secondary(void)
 
 	for (i = 0; i < loongson_sysconf.nr_cpus; i++)
 		loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]);
+
+	per_cpu(cpu_state, cpu) = CPU_ONLINE;
+
+	i = 0;
+	__get_cpu_var(core0_c0count) = 0;
+	loongson3_send_ipi_single(0, SMP_ASK_C0COUNT);
+	while (!__get_cpu_var(core0_c0count)) {
+		i++;
+		cpu_relax();
+	}
+
+	if (i > MAX_LOOPS)
+		i = MAX_LOOPS;
+	initcount = __get_cpu_var(core0_c0count) + i;
+	write_c0_count(initcount);
 }
 
 void loongson3_smp_finish(void)
@@ -234,6 +263,8 @@ void __init loongson3_smp_setup(void)
 
 void __init loongson3_prepare_cpus(unsigned int max_cpus)
 {
+	init_cpu_present(cpu_possible_mask);
+	per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
 }
 
 /*
@@ -267,6 +298,138 @@ void __init loongson3_cpus_done(void)
 {
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+
+static int loongson3_cpu_disable(void)
+{
+	unsigned long flags;
+	unsigned int cpu = smp_processor_id();
+
+	if (cpu == 0)
+		return -EBUSY;
+
+	set_cpu_online(cpu, false);
+	cpu_clear(cpu, cpu_callin_map);
+	local_irq_save(flags);
+	fixup_irqs();
+	local_irq_restore(flags);
+	flush_cache_all();
+	local_flush_tlb_all();
+
+	return 0;
+}
+
+
+static void loongson3_cpu_die(unsigned int cpu)
+{
+	while (per_cpu(cpu_state, cpu) != CPU_DEAD)
+		cpu_relax();
+
+	mb();
+}
+
+/* To shutdown a core in Loongson 3, the target core should go to CKSEG1 and
+ * flush all L1 entries at first. Then, another core (usually Core 0) can
+ * safely disable the clock of the target core. loongson3_play_dead() is
+ * called via CKSEG1 (uncached and unmmaped) */
+void loongson3_play_dead(int *state_addr)
+{
+	__asm__ __volatile__(
+		"   .set push                     \n"
+		"   .set noreorder                \n"
+		"   li $t0, 0x80000000            \n" /* KSEG0 */
+		"   move $t1, %0                  \n" /* num of L1 entries */
+		"1: cache 0, 0($t0)               \n" /* flush L1 ICache */
+		"   cache 0, 1($t0)               \n"
+		"   cache 0, 2($t0)               \n"
+		"   cache 0, 3($t0)               \n"
+		"   cache 1, 0($t0)               \n" /* flush L1 DCache */
+		"   cache 1, 1($t0)               \n"
+		"   cache 1, 2($t0)               \n"
+		"   cache 1, 3($t0)               \n"
+		"   addiu $t0, $t0, 0x20          \n"
+		"   bnez  $t1, 1b                 \n"
+		"   addiu $t1, $t1, -1            \n"
+		"   li    $t0, 0x7                \n" /* *state_addr = CPU_DEAD; */
+		"   sw    $t0, 0($a0)             \n"
+		"   sync                          \n"
+		"   cache 21, 0($a0)              \n" /* flush entry of *state_addr */
+		"   .set pop                      \n"
+		: /* No Output */
+		: "r" (cpu_data[0].dcache.sets));
+
+	__asm__ __volatile__(
+		"   .set push                     \n"
+		"   .set noreorder                \n"
+		"   .set mips64                   \n"
+		"   mfc0  $t2, $15, 1             \n"
+		"   andi  $t2, 0x3ff              \n"
+		"   dli   $t0, 0x900000003ff01000 \n"
+		"   andi  $t3, $t2, 0x3           \n"
+		"   sll   $t3, 8                  \n"  /* get cpu id */
+		"   or    $t0, $t0, $t3           \n"
+		"   andi  $t1, $t2, 0xc           \n"
+		"   dsll  $t1, 42                 \n"  /* get node id */
+		"   or    $t0, $t0, $t1           \n"
+		"1: li    $a0, 0x100              \n"  /* wait for init loop */
+		"2: bnez  $a0, 2b                 \n"  /* idle loop */
+		"   addiu $a0, -1                 \n"
+		"   lw    $v0, 0x20($t0)          \n"  /* get PC via mailbox */
+		"   beqz  $v0, 1b                 \n"
+		"   nop                           \n"
+		"   ld    $sp, 0x28($t0)          \n"  /* get SP via mailbox */
+		"   ld    $gp, 0x30($t0)          \n"  /* get GP via mailbox */
+		"   ld    $a1, 0x38($t0)          \n"
+		"   jr    $v0                     \n"  /* jump to initial PC */
+		"   nop                           \n"
+		"   .set pop                      \n");
+}
+
+void play_dead(void)
+{
+	int *state_addr;
+	unsigned int cpu = smp_processor_id();
+	void (*play_dead_at_ckseg1)(int *);
+
+	idle_task_exit();
+	play_dead_at_ckseg1 =
+		(void *)CKSEG1ADDR((unsigned long)loongson3_play_dead);
+	state_addr = &per_cpu(cpu_state, cpu);
+	mb();
+	play_dead_at_ckseg1(state_addr);
+}
+
+#define CPU_POST_DEAD_FROZEN	(CPU_POST_DEAD | CPU_TASKS_FROZEN)
+static int loongson3_cpu_callback(struct notifier_block *nfb,
+	unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (unsigned long)hcpu;
+
+	switch (action) {
+	case CPU_POST_DEAD:
+	case CPU_POST_DEAD_FROZEN:
+		pr_info("Disable clock for CPU#%d\n", cpu);
+		LOONGSON_CHIPCFG0 &= ~(1 << (12 + cpu));
+		break;
+	case CPU_UP_PREPARE:
+	case CPU_UP_PREPARE_FROZEN:
+		pr_info("Enable clock for CPU#%d\n", cpu);
+		LOONGSON_CHIPCFG0 |= 1 << (12 + cpu);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static int register_loongson3_notifier(void)
+{
+	hotcpu_notifier(loongson3_cpu_callback, 0);
+	return 0;
+}
+early_initcall(register_loongson3_notifier);
+
+#endif
+
 struct plat_smp_ops loongson3_smp_ops = {
 	.send_ipi_single = loongson3_send_ipi_single,
 	.send_ipi_mask = loongson3_send_ipi_mask,
@@ -276,4 +439,8 @@ struct plat_smp_ops loongson3_smp_ops = {
 	.boot_secondary = loongson3_boot_secondary,
 	.smp_setup = loongson3_smp_setup,
 	.prepare_cpus = loongson3_prepare_cpus,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_disable = loongson3_cpu_disable,
+	.cpu_die = loongson3_cpu_die,
+#endif
 };
-- 
1.7.7.3

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

* [PATCH V16 12/12] MIPS: Loongson: Add a Loongson-3 default config file
  2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
                   ` (10 preceding siblings ...)
  2014-01-08  2:44 ` [PATCH V16 11/12] MIPS: Loongson 3: Add CPU hotplug support Huacai Chen
@ 2014-01-08  2:44 ` Huacai Chen
  2014-01-08  7:26 ` [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support John Crispin
  2014-01-18  9:38 ` Andreas Barth
  13 siblings, 0 replies; 55+ messages in thread
From: Huacai Chen @ 2014-01-08  2:44 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: John Crispin, Steven J. Hill, Aurelien Jarno, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Huacai Chen, Hongliang Tao, Hua Yan

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Hongliang Tao <taohl@lemote.com>
Signed-off-by: Hua Yan <yanh@lemote.com>
---
 arch/mips/configs/loongson3_defconfig |  342 +++++++++++++++++++++++++++++++++
 1 files changed, 342 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/configs/loongson3_defconfig

diff --git a/arch/mips/configs/loongson3_defconfig b/arch/mips/configs/loongson3_defconfig
new file mode 100644
index 0000000..65dfe57
--- /dev/null
+++ b/arch/mips/configs/loongson3_defconfig
@@ -0,0 +1,342 @@
+CONFIG_MACH_LOONGSON=y
+CONFIG_SWIOTLB=y
+CONFIG_LEMOTE_MACH3A=y
+CONFIG_CPU_LOONGSON3=y
+CONFIG_64BIT=y
+CONFIG_PAGE_SIZE_16KB=y
+CONFIG_KSM=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4
+CONFIG_HZ_256=y
+CONFIG_PREEMPT=y
+CONFIG_KEXEC=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_LZMA=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CPUSETS=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_BLK_CGROUP=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_EMBEDDED=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_PCI=y
+CONFIG_HT_PCI=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=y
+# CONFIG_PCIEAER is not set
+CONFIG_PCIEASPM_PERFORMANCE=y
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_SHPC=m
+CONFIG_BINFMT_MISC=m
+CONFIG_MIPS32_COMPAT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
+CONFIG_PM_RUNTIME=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_IP_VS=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_IP_SCTP=m
+CONFIG_L2TP=m
+CONFIG_BRIDGE=m
+CONFIG_CFG80211=m
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=m
+CONFIG_RFKILL=m
+CONFIG_RFKILL_INPUT=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=m
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=y
+CONFIG_MEGARAID_MAILBOX=y
+CONFIG_MEGARAID_LEGACY=y
+CONFIG_MEGARAID_SAS=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_PATA_ATIIXP=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_NETDEVICES=y
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_HP is not set
+CONFIG_E1000=y
+CONFIG_E1000E=y
+CONFIG_IGB=y
+CONFIG_IXGB=y
+CONFIG_IXGBE=y
+# CONFIG_NET_VENDOR_I825XX is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_R8169=y
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_TOSHIBA is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_ATH_CARDS=m
+CONFIG_ATH9K=m
+CONFIG_HOSTAP=m
+CONFIG_INPUT_POLLDEV=m
+CONFIG_INPUT_SPARSEKMAP=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_MOUSE_PS2_SENTELIC=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_RAW=m
+CONFIG_LEGACY_PTY_COUNT=16
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=16
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_HW_RANDOM=y
+CONFIG_RAW_DRIVER=m
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_PIIX4=y
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM93=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_MEDIA_SUPPORT=m
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_DRM=y
+CONFIG_DRM_RADEON=y
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB_RADEON=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=m
+CONFIG_BACKLIGHT_GENERIC=m
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+# CONFIG_SND_ISA is not set
+CONFIG_SND_HDA_INTEL=m
+CONFIG_SND_HDA_PATCH_LOADER=y
+# CONFIG_SND_USB is not set
+CONFIG_HID_A4TECH=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_USB=y
+CONFIG_USB_MON=y
+CONFIG_USB_XHCI_HCD=m
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_DMADEVICES=y
+CONFIG_PM_DEVFREQ=y
+CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
+CONFIG_DEVFREQ_GOV_PERFORMANCE=y
+CONFIG_DEVFREQ_GOV_POWERSAVE=y
+CONFIG_DEVFREQ_GOV_USERSPACE=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=936
+CONFIG_FAT_DEFAULT_IOCHARSET="gb2312"
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=m
+CONFIG_NFSD=m
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_CIFS=m
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_FRAME_WARN=1024
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_RCU_CPU_STALL_VERBOSE is not set
+# CONFIG_FTRACE is not set
+CONFIG_SECURITY=y
+CONFIG_SECURITYFS=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_PATH=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_DEFLATE=m
-- 
1.7.7.3

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

* Re: [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support
  2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
                   ` (11 preceding siblings ...)
  2014-01-08  2:44 ` [PATCH V16 12/12] MIPS: Loongson: Add a Loongson-3 default config file Huacai Chen
@ 2014-01-08  7:26 ` John Crispin
  2014-01-18  9:38 ` Andreas Barth
  13 siblings, 0 replies; 55+ messages in thread
From: John Crispin @ 2014-01-08  7:26 UTC (permalink / raw)
  To: linux-mips


> This patchset is prepared for the next 3.14 release for Linux/MIPS.

Hi,

we don't accept patches post rc5. this series will have to wait till 3.15.

	John

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

* Re: [PATCH V16 01/12] MIPS: Loongson: Add basic Loongson-3 definition
  2014-01-08  2:44 ` [PATCH V16 01/12] MIPS: Loongson: Add basic Loongson-3 definition Huacai Chen
@ 2014-01-08 19:58   ` Aurelien Jarno
  0 siblings, 0 replies; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-08 19:58 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Wed, Jan 08, 2014 at 10:44:17AM +0800, Huacai Chen wrote:
> Loongson-3 is a multi-core MIPS family CPU, it support MIPS64R2 fully.
> Loongson-3 has the same IMP field (0x6300) as Loongson-2.
> 
> Loongson-3 has a hardware-maintained cache, system software doesn't
> need to maintain coherency.
> 
> Loongson-3A is the first revision of Loongson-3, and it is the quad-
> core version of Loongson-2G. Loongson-3A has a simplified version named
> Loongson-2Gq, the main difference between Loongson-3A/2Gq is 3A has two
> HyperTransport controller but 2Gq has only one. HT0 is used for cross-
> chip interconnection and HT1 is used to link PCI bus. Therefore, 2Gq
> cannot support NUMA but 3A can. For software, Loongson-2Gq is simply
> identified as Loongson-3A.
> 
> Exsisting Loongson family CPUs:
> Loongson-1: Loongson-1A, Loongson-1B, they are 32-bit MIPS CPUs.
> Loongson-2: Loongson-2E, Loongson-2F, Loongson-2G, they are 64-bit
>             single-core MIPS CPUs.
> Loongson-3: Loongson-3A(including so-called Loongson-2Gq), they are
>             64-bit multi-core MIPS CPUs.
> 
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>  arch/mips/include/asm/addrspace.h            |    2 ++
>  arch/mips/include/asm/cpu.h                  |    5 +++--
>  arch/mips/include/asm/mach-loongson/spaces.h |   13 +++++++++++++
>  arch/mips/include/asm/module.h               |    2 ++
>  arch/mips/include/asm/pgtable-bits.h         |    9 +++++++++
>  5 files changed, 29 insertions(+), 2 deletions(-)
>  create mode 100644 arch/mips/include/asm/mach-loongson/spaces.h
> 
> diff --git a/arch/mips/include/asm/addrspace.h b/arch/mips/include/asm/addrspace.h
> index 3f74545..41c030e 100644
> --- a/arch/mips/include/asm/addrspace.h
> +++ b/arch/mips/include/asm/addrspace.h
> @@ -116,7 +116,9 @@
>  #define K_CALG_UNCACHED		2
>  #define K_CALG_NONCOHERENT	3
>  #define K_CALG_COH_EXCL		4
> +#ifndef K_CALG_COH_SHAREABLE
>  #define K_CALG_COH_SHAREABLE	5
> +#endif
>  #define K_CALG_NOTUSED		6
>  #define K_CALG_UNCACHED_ACCEL	7
>  
> diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
> index d2035e1..7fffaf1 100644
> --- a/arch/mips/include/asm/cpu.h
> +++ b/arch/mips/include/asm/cpu.h
> @@ -224,6 +224,7 @@
>  #define PRID_REV_LOONGSON1B	0x0020
>  #define PRID_REV_LOONGSON2E	0x0002
>  #define PRID_REV_LOONGSON2F	0x0003
> +#define PRID_REV_LOONGSON3A	0x0005
>  
>  /*
>   * Older processors used to encode processor version and revision in two
> @@ -295,8 +296,8 @@ enum cpu_type_enum {
>  	 * MIPS64 class processors
>  	 */
>  	CPU_5KC, CPU_5KE, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2,
> -	CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS, CPU_CAVIUM_OCTEON2,
> -	CPU_CAVIUM_OCTEON3, CPU_XLR, CPU_XLP,
> +	CPU_LOONGSON3, CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS,
> +	CPU_CAVIUM_OCTEON2, CPU_CAVIUM_OCTEON3, CPU_XLR, CPU_XLP,
>  
>  	CPU_LAST
>  };
> diff --git a/arch/mips/include/asm/mach-loongson/spaces.h b/arch/mips/include/asm/mach-loongson/spaces.h
> new file mode 100644
> index 0000000..d368d95
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson/spaces.h
> @@ -0,0 +1,13 @@
> +#ifndef __ASM_MACH_LOONGSON_SPACES_H_
> +#define __ASM_MACH_LOONGSON_SPACES_H_
> +
> +#ifndef CAC_BASE
> +#if defined(CONFIG_64BIT)
> +#define CAC_BASE        _AC(0x9800000000000000, UL)
> +#endif /* CONFIG_64BIT */
> +#endif /* CONFIG_CAC_BASE */
> +
> +#define K_CALG_COH_SHAREABLE	3
> +
> +#include <asm/mach-generic/spaces.h>
> +#endif
> diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
> index 44b705d..c2edae3 100644
> --- a/arch/mips/include/asm/module.h
> +++ b/arch/mips/include/asm/module.h
> @@ -126,6 +126,8 @@ search_module_dbetables(unsigned long addr)
>  #define MODULE_PROC_FAMILY "LOONGSON1 "
>  #elif defined CONFIG_CPU_LOONGSON2
>  #define MODULE_PROC_FAMILY "LOONGSON2 "
> +#elif defined CONFIG_CPU_LOONGSON3
> +#define MODULE_PROC_FAMILY "LOONGSON3 "
>  #elif defined CONFIG_CPU_CAVIUM_OCTEON
>  #define MODULE_PROC_FAMILY "OCTEON "
>  #elif defined CONFIG_CPU_XLR
> diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h
> index 32aea48..e592f36 100644
> --- a/arch/mips/include/asm/pgtable-bits.h
> +++ b/arch/mips/include/asm/pgtable-bits.h
> @@ -235,6 +235,15 @@ static inline uint64_t pte_to_entrylo(unsigned long pte_val)
>  #define _CACHE_CACHABLE_NONCOHERENT (5<<_CACHE_SHIFT)
>  #define _CACHE_UNCACHED_ACCELERATED (7<<_CACHE_SHIFT)
>  
> +#elif defined(CONFIG_CPU_LOONGSON3)
> +
> +/* Using COHERENT flag for NONCOHERENT doesn't hurt. */
> +
> +#define _CACHE_UNCACHED             (2<<_CACHE_SHIFT)  /* LOONGSON       */
> +#define _CACHE_CACHABLE_NONCOHERENT (3<<_CACHE_SHIFT)  /* LOONGSON       */
> +#define _CACHE_CACHABLE_COHERENT    (3<<_CACHE_SHIFT)  /* LOONGSON-3     */
> +#define _CACHE_UNCACHED_ACCELERATED (7<<_CACHE_SHIFT)  /* LOONGSON       */
> +
>  #else
>  
>  #define _CACHE_CACHABLE_NO_WA	    (0<<_CACHE_SHIFT)  /* R4600 only	  */

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 02/12] MIPS: Loongson: Add basic Loongson-3 CPU support
  2014-01-08  2:44 ` [PATCH V16 02/12] MIPS: Loongson: Add basic Loongson-3 CPU support Huacai Chen
@ 2014-01-08 19:58   ` Aurelien Jarno
       [not found]     ` <CAAhV-H4tx=sCk=iUwuCfnCS+rbmtu5Y_UcpAn6JXDoobA+OGrQ@mail.gmail.com>
  0 siblings, 1 reply; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-08 19:58 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Wed, Jan 08, 2014 at 10:44:18AM +0800, Huacai Chen wrote:
> Basic Loongson-3 CPU support include CPU probing and TLB/cache
> initializing.
> 
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>  arch/mips/include/asm/cpu-type.h |    4 ++
>  arch/mips/kernel/cpu-probe.c     |   14 ++++++--
>  arch/mips/mm/c-r4k.c             |   59 ++++++++++++++++++++++++++++++++++++++
>  arch/mips/mm/tlb-r4k.c           |    5 ++-
>  arch/mips/mm/tlbex.c             |    1 +
>  5 files changed, 77 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h
> index 4a402cc..a591e63 100644
> --- a/arch/mips/include/asm/cpu-type.h
> +++ b/arch/mips/include/asm/cpu-type.h
> @@ -20,6 +20,10 @@ static inline int __pure __get_cpu_type(const int cpu_type)
>  	case CPU_LOONGSON2:
>  #endif
>  
> +#ifdef CONFIG_SYS_HAS_CPU_LOONGSON3
> +	case CPU_LOONGSON3:
> +#endif
> +
>  #ifdef CONFIG_SYS_HAS_CPU_LOONGSON1B
>  	case CPU_LOONGSON1:
>  #endif
> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> index c814287..4bc81b2 100644
> --- a/arch/mips/kernel/cpu-probe.c
> +++ b/arch/mips/kernel/cpu-probe.c
> @@ -639,17 +639,23 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
>  			     MIPS_CPU_LLSC;
>  		c->tlbsize = 64;
>  		break;
> -	case PRID_IMP_LOONGSON2:
> -		c->cputype = CPU_LOONGSON2;
> -		__cpu_name[cpu] = "ICT Loongson-2";
> -
> +	case PRID_IMP_LOONGSON2: /* Loongson-2/3 have the same PRID_IMP field */

What about renaming that as something like PRID_IMP_LOONGSON23 given
it is for both Loongson 2 and 3?

>  		switch (c->processor_id & PRID_REV_MASK) {
>  		case PRID_REV_LOONGSON2E:
> +			c->cputype = CPU_LOONGSON2;
> +			__cpu_name[cpu] = "ICT Loongson-2E";
>  			set_elf_platform(cpu, "loongson2e");
>  			break;
>  		case PRID_REV_LOONGSON2F:
> +			c->cputype = CPU_LOONGSON2;
> +			__cpu_name[cpu] = "ICT Loongson-2F";
>  			set_elf_platform(cpu, "loongson2f");
>  			break;

As remarked by Aaro Koskinen, changing the names of the Loongson 2 CPUs
(which is displayedd in /proc/cpuinfo) will break at least
GCC -march=native option. The name should be left unchanged.

> +		case PRID_REV_LOONGSON3A:
> +			c->cputype = CPU_LOONGSON3;
> +			__cpu_name[cpu] = "ICT Loongson-3A";
> +			set_elf_platform(cpu, "loongson3a");
> +			break;
>  		}
>  
>  		set_isa(c, MIPS_CPU_ISA_III);
> diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
> index 73f02da..cc02527 100644
> --- a/arch/mips/mm/c-r4k.c
> +++ b/arch/mips/mm/c-r4k.c
> @@ -348,6 +348,7 @@ static inline void local_r4k___flush_cache_all(void * args)
>  {
>  	switch (current_cpu_type()) {
>  	case CPU_LOONGSON2:
> +	case CPU_LOONGSON3:
>  	case CPU_R4000SC:
>  	case CPU_R4000MC:
>  	case CPU_R4400SC:
> @@ -1003,6 +1004,33 @@ static void probe_pcache(void)
>  		c->dcache.waybit = 0;
>  		break;
>  
> +	case CPU_LOONGSON3:
> +		config1 = read_c0_config1();
> +		lsize = (config1 >> 19) & 7;
> +		if (lsize)
> +			c->icache.linesz = 2 << lsize;
> +		else
> +			c->icache.linesz = 0;

Sorry to not have seen that before, but it can also be written as:

	c->icache.linesz = lsize ? (2 << lsize) : 0;

That said the current version is also fine, so as you prefer.

> +		c->icache.sets = 64 << ((config1 >> 22) & 7);
> +		c->icache.ways = 1 + ((config1 >> 16) & 7);
> +		icache_size = c->icache.sets *
> +					  c->icache.ways *
> +					  c->icache.linesz;
> +		c->icache.waybit = 0;
> +
> +		lsize = (config1 >> 10) & 7;
> +		if (lsize)
> +			c->dcache.linesz = 2 << lsize;
> +		else
> +			c->dcache.linesz = 0;
> +		c->dcache.sets = 64 << ((config1 >> 13) & 7);
> +		c->dcache.ways = 1 + ((config1 >> 7) & 7);
> +		dcache_size = c->dcache.sets *
> +					  c->dcache.ways *
> +					  c->dcache.linesz;
> +		c->dcache.waybit = 0;
> +		break;
> +
>  	default:
>  		if (!(config & MIPS_CONF_M))
>  			panic("Don't know how to probe P-caches on this cpu.");
> @@ -1222,6 +1250,33 @@ static void __init loongson2_sc_init(void)
>  	c->options |= MIPS_CPU_INCLUSIVE_CACHES;
>  }
>  
> +static void __init loongson3_sc_init(void)
> +{
> +	struct cpuinfo_mips *c = &current_cpu_data;
> +	unsigned int config2, lsize;
> +
> +	config2 = read_c0_config2();
> +	lsize = (config2 >> 4) & 15;
> +	if (lsize)
> +		c->scache.linesz = 2 << lsize;
> +	else
> +		c->scache.linesz = 0;
> +	c->scache.sets = 64 << ((config2 >> 8) & 15);
> +	c->scache.ways = 1 + (config2 & 15);
> +
> +	scache_size = c->scache.sets *
> +				  c->scache.ways *
> +				  c->scache.linesz;
> +	/* Loongson-3 has 4 cores, 1MB scache for each. scaches are shared */
> +	scache_size *= 4;
> +	c->scache.waybit = 0;
> +	pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
> +	       scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
> +	if (scache_size)
> +		c->options |= MIPS_CPU_INCLUSIVE_CACHES;
> +	return;
> +}
> +
>  extern int r5k_sc_init(void);
>  extern int rm7k_sc_init(void);
>  extern int mips_sc_init(void);
> @@ -1274,6 +1329,10 @@ static void setup_scache(void)
>  		loongson2_sc_init();
>  		return;
>  
> +	case CPU_LOONGSON3:
> +		loongson3_sc_init();
> +		return;
> +
>  	case CPU_XLP:
>  		/* don't need to worry about L2, fully coherent */
>  		return;
> diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
> index da3b0b9..298f281 100644
> --- a/arch/mips/mm/tlb-r4k.c
> +++ b/arch/mips/mm/tlb-r4k.c
> @@ -53,13 +53,14 @@ extern void build_tlb_refill_handler(void);
>  #endif /* CONFIG_MIPS_MT_SMTC */
>  
>  /*
> - * LOONGSON2 has a 4 entry itlb which is a subset of dtlb,
> - * unfortrunately, itlb is not totally transparent to software.
> + * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb,
> + * unfortunately, itlb is not totally transparent to software.
>   */
>  static inline void flush_itlb(void)
>  {
>  	switch (current_cpu_type()) {
>  	case CPU_LOONGSON2:
> +	case CPU_LOONGSON3:
>  		write_c0_diag(4);
>  		break;
>  	default:
> diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
> index 183f2b5..f89124c 100644
> --- a/arch/mips/mm/tlbex.c
> +++ b/arch/mips/mm/tlbex.c
> @@ -579,6 +579,7 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
>  	case CPU_BMIPS4380:
>  	case CPU_BMIPS5000:
>  	case CPU_LOONGSON2:
> +	case CPU_LOONGSON3:
>  	case CPU_R5500:
>  		if (m4kc_tlbp_war())
>  			uasm_i_nop(p);
> -- 
> 1.7.7.3
> 
> 

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 03/12] MIPS: Loongson 3: Add Lemote-3A machtypes definition
  2014-01-08  2:44 ` [PATCH V16 03/12] MIPS: Loongson 3: Add Lemote-3A machtypes definition Huacai Chen
@ 2014-01-08 19:58   ` Aurelien Jarno
  0 siblings, 0 replies; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-08 19:58 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Wed, Jan 08, 2014 at 10:44:19AM +0800, Huacai Chen wrote:
> Add four Loongson-3 based machine types:
> MACH_LEMOTE_A1004/MACH_LEMOTE_A1201 are laptops;
> MACH_LEMOTE_A1101 is mini-itx;
> MACH_LEMOTE_A1205 is all-in-one machine.
> 
> The most significant differrent between A1004/A1201 and A1101/A1205 is
> the laptops have EC but others don't.
> 
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>  arch/mips/include/asm/bootinfo.h              |   24 +++++++++++++++---------
>  arch/mips/include/asm/mach-loongson/machine.h |    6 ++++++
>  arch/mips/loongson/common/machtype.c          |    4 ++++
>  3 files changed, 25 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
> index 4d2cdea..09956a0 100644
> --- a/arch/mips/include/asm/bootinfo.h
> +++ b/arch/mips/include/asm/bootinfo.h
> @@ -61,15 +61,21 @@
>  /*
>   * Valid machtype for Loongson family
>   */
> -#define MACH_LOONGSON_UNKNOWN  0
> -#define MACH_LEMOTE_FL2E       1
> -#define MACH_LEMOTE_FL2F       2
> -#define MACH_LEMOTE_ML2F7      3
> -#define MACH_LEMOTE_YL2F89     4
> -#define MACH_DEXXON_GDIUM2F10  5
> -#define MACH_LEMOTE_NAS	       6
> -#define MACH_LEMOTE_LL2F       7
> -#define MACH_LOONGSON_END      8
> +enum loongson_machine_type {
> +	MACH_LOONGSON_UNKNOWN,
> +	MACH_LEMOTE_FL2E,
> +	MACH_LEMOTE_FL2F,
> +	MACH_LEMOTE_ML2F7,
> +	MACH_LEMOTE_YL2F89,
> +	MACH_DEXXON_GDIUM2F10,
> +	MACH_LEMOTE_NAS,
> +	MACH_LEMOTE_LL2F,
> +	MACH_LEMOTE_A1004,
> +	MACH_LEMOTE_A1101,
> +	MACH_LEMOTE_A1201,
> +	MACH_LEMOTE_A1205,
> +	MACH_LOONGSON_END
> +};
>  
>  /*
>   * Valid machtype for group INGENIC
> diff --git a/arch/mips/include/asm/mach-loongson/machine.h b/arch/mips/include/asm/mach-loongson/machine.h
> index 3810d5c..1b1f592 100644
> --- a/arch/mips/include/asm/mach-loongson/machine.h
> +++ b/arch/mips/include/asm/mach-loongson/machine.h
> @@ -24,4 +24,10 @@
>  
>  #endif
>  
> +#ifdef CONFIG_LEMOTE_MACH3A
> +
> +#define LOONGSON_MACHTYPE MACH_LEMOTE_A1101
> +
> +#endif /* CONFIG_LEMOTE_MACH3A */
> +
>  #endif /* __ASM_MACH_LOONGSON_MACHINE_H */
> diff --git a/arch/mips/loongson/common/machtype.c b/arch/mips/loongson/common/machtype.c
> index 4becd4f..1a47979 100644
> --- a/arch/mips/loongson/common/machtype.c
> +++ b/arch/mips/loongson/common/machtype.c
> @@ -27,6 +27,10 @@ static const char *system_types[] = {
>  	[MACH_DEXXON_GDIUM2F10]		"dexxon-gdium-2f",
>  	[MACH_LEMOTE_NAS]		"lemote-nas-2f",
>  	[MACH_LEMOTE_LL2F]		"lemote-lynloong-2f",
> +	[MACH_LEMOTE_A1004]		"lemote-3a-notebook-a1004",
> +	[MACH_LEMOTE_A1101]		"lemote-3a-itx-a1101",
> +	[MACH_LEMOTE_A1201]		"lemote-2gq-notebook-a1201",
> +	[MACH_LEMOTE_A1205]		"lemote-2gq-aio-a1205",
>  	[MACH_LOONGSON_END]		NULL,
>  };

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 04/12] MIPS: Loongson: Add UEFI-like firmware interface (LEFI) support
  2014-01-08  2:44 ` [PATCH V16 04/12] MIPS: Loongson: Add UEFI-like firmware interface (LEFI) support Huacai Chen
@ 2014-01-08 22:58   ` Aurelien Jarno
  2014-01-09 12:43       ` Alex Smith
       [not found]     ` <CAAhV-H64BXsw5CBL-KW1eqXkYcadhHF2NeBH9YmWQz046Lpzzw@mail.gmail.com>
  2014-01-09 12:37     ` Alex Smith
  1 sibling, 2 replies; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-08 22:58 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Wed, Jan 08, 2014 at 10:44:20AM +0800, Huacai Chen wrote:
> The new UEFI-like firmware interface (LEFI, i.e. Loongson Unified
> Firmware Interface) has 3 advantages:
> 
> 1, Firmware export a physical memory map which is similar to X86's
>    E820 map, so prom_init_memory() will be more elegant that #ifdef
>    clauses can be removed.
> 2, Firmware export a pci irq routing table, we no longer need pci
>    irq routing fixup in kernel's code.
> 3, Firmware has a built-in vga bios, and its address is exported,
>    the linux kernel no longer need an embedded blob.
> 
> With the LEFI interface, Loongson-3A/2G and all their successors can use
> a unified kernel. All Loongson-based machines support this new interface
> except 2E/2F series.
> 
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>  arch/mips/include/asm/mach-loongson/boot_param.h |  159 ++++++++++++++++++++++
>  arch/mips/include/asm/mach-loongson/loongson.h   |    4 +-
>  arch/mips/loongson/common/env.c                  |   64 +++++++--
>  arch/mips/loongson/common/init.c                 |    9 +-
>  arch/mips/loongson/common/mem.c                  |   42 ++++++
>  arch/mips/loongson/common/pci.c                  |    6 +-
>  arch/mips/loongson/common/reset.c                |   21 +++
>  7 files changed, 285 insertions(+), 20 deletions(-)
>  create mode 100644 arch/mips/include/asm/mach-loongson/boot_param.h
> 
> diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h
> new file mode 100644
> index 0000000..234c0eb
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson/boot_param.h
> @@ -0,0 +1,159 @@
> +#ifndef __ASM_MACH_LOONGSON_BOOT_PARAM_H_
> +#define __ASM_MACH_LOONGSON_BOOT_PARAM_H_
> +
> +#define SYSTEM_RAM_LOW		1
> +#define SYSTEM_RAM_HIGH		2
> +#define MEM_RESERVED		3
> +#define PCI_IO			4
> +#define PCI_MEM			5
> +#define LOONGSON_CFG_REG	6
> +#define VIDEO_ROM		7
> +#define ADAPTER_ROM		8
> +#define ACPI_TABLE		9
> +#define MAX_MEMORY_TYPE		10
> +
> +#define LOONGSON3_BOOT_MEM_MAP_MAX 128
> +struct efi_memory_map_loongson {
> +	u16 vers;	/* version of efi_memory_map */
> +	u32 nr_map;	/* number of memory_maps */
> +	u32 mem_freq;	/* memory frequence */
> +	struct mem_map {
> +		u32 node_id;	/* node_id which memory attached to */
> +		u32 mem_type;	/* system memory, pci memory, pci io, etc. */
> +		u64 mem_start;	/* memory map start address */
> +		u32 mem_size;	/* each memory_map size, not the total size */
> +	} map[LOONGSON3_BOOT_MEM_MAP_MAX];
> +} __packed;
> +
> +enum loongson_cpu_type {
> +	Loongson_2E = 0,
> +	Loongson_2F = 1,
> +	Loongson_3A = 2,
> +	Loongson_3B = 3,
> +	Loongson_1A = 4,
> +	Loongson_1B = 5
> +};
> +
> +/*
> + * Capability and feature descriptor structure for MIPS CPU
> + */
> +struct efi_cpuinfo_loongson {
> +	u16 vers;     /* version of efi_cpuinfo_loongson */
> +	u32 processor_id; /* PRID, e.g. 6305, 6306 */
> +	u32 cputype;  /* Loongson_3A/3B, etc. */
> +	u32 total_node;   /* num of total numa nodes */
> +	u32 cpu_startup_core_id; /* Core id */
> +	u32 cpu_clock_freq; /* cpu_clock */
> +	u32 nr_cpus;
> +} __packed;
> +
> +struct system_loongson {
> +	u16 vers;     /* version of system_loongson */
> +	u32 ccnuma_smp; /* 0: no numa; 1: has numa */
> +	u32 sing_double_channel; /* 1:single; 2:double */
> +} __packed;
> +
> +struct irq_source_routing_table {
> +	u16 vers;
> +	u16 size;
> +	u16 rtr_bus;
> +	u16 rtr_devfn;
> +	u32 vendor;
> +	u32 device;
> +	u32 PIC_type;   /* conform use HT or PCI to route to CPU-PIC */
> +	u64 ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */
> +	u64 ht_enable;  /* irqs used in this PIC */
> +	u32 node_id;    /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */
> +	u64 pci_mem_start_addr;
> +	u64 pci_mem_end_addr;
> +	u64 pci_io_start_addr;
> +	u64 pci_io_end_addr;
> +	u64 pci_config_addr;
> +} __packed;
> +
> +struct interface_info {
> +	u16 vers; /* version of the specificition */
> +	u16 size;
> +	u8  flag;
> +	char description[64];
> +} __packed;
> +
> +#define MAX_RESOURCE_NUMBER 128
> +struct resource_loongson {
> +	u64 start; /* resource start address */
> +	u64 end;   /* resource end address */
> +	char name[64];
> +	u32 flags;
> +};
> +
> +struct archdev_data {};  /* arch specific additions */
> +
> +struct board_devices {
> +	char name[64];    /* hold the device name */
> +	u32 num_resources; /* number of device_resource */
> +	/* for each device's resource */
> +	struct resource_loongson resource[MAX_RESOURCE_NUMBER];
> +	/* arch specific additions */
> +	struct archdev_data archdata;
> +};
> +
> +struct loongson_special_attribute {
> +	u16 vers;     /* version of this special */
> +	char special_name[64]; /* special_atribute_name */
> +	u32 loongson_special_type; /* type of special device */
> +	/* for each device's resource */
> +	struct resource_loongson resource[MAX_RESOURCE_NUMBER];
> +};
> +
> +struct loongson_params {
> +	u64 memory_offset;	/* efi_memory_map_loongson struct offset */
> +	u64 cpu_offset;		/* efi_cpuinfo_loongson struct offset */
> +	u64 system_offset;	/* system_loongson struct offset */
> +	u64 irq_offset;		/* irq_source_routing_table struct offset */
> +	u64 interface_offset;	/* interface_info struct offset */
> +	u64 special_offset;	/* loongson_special_attribute struct offset */
> +	u64 boarddev_table_offset;  /* board_devices offset */
> +};
> +
> +struct smbios_tables {
> +	u16 vers;     /* version of smbios */
> +	u64 vga_bios; /* vga_bios address */
> +	struct loongson_params lp;
> +};
> +
> +struct efi_reset_system_t {
> +	u64 ResetCold;
> +	u64 ResetWarm;
> +	u64 ResetType;
> +	u64 Shutdown;
> +};
> +
> +struct efi_loongson {
> +	u64 mps;	/* MPS table */
> +	u64 acpi;	/* ACPI table (IA64 ext 0.71) */
> +	u64 acpi20;	/* ACPI table (ACPI 2.0) */
> +	struct smbios_tables smbios;	/* SM BIOS table */
> +	u64 sal_systab;	/* SAL system table */
> +	u64 boot_info;	/* boot info table */
> +};
> +
> +struct boot_params {
> +	struct efi_loongson efi;
> +	struct efi_reset_system_t reset_system;
> +};
> +
> +struct loongson_system_configuration {
> +	u32 nr_cpus;
> +	enum loongson_cpu_type cputype;
> +	u64 ht_control_base;
> +	u64 pci_mem_start_addr;
> +	u64 pci_mem_end_addr;
> +	u64 pci_io_base;
> +	u64 restart_addr;
> +	u64 poweroff_addr;
> +	u64 vgabios_addr;
> +};
> +
> +extern struct efi_memory_map_loongson *emap;
> +extern struct loongson_system_configuration loongson_sysconf;

Thanks a lot for the loongson_sysconf struct, it looks a lot more clean
now. What about emap? Isn't there any risk that the kernel reuse the
corresponding memory and that its content is lost? It should be possible
to hold a copy of this struct in loongson_sysconf.


> +#endif
> diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
> index b286534..5913ea0 100644
> --- a/arch/mips/include/asm/mach-loongson/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson/loongson.h
> @@ -24,8 +24,8 @@ extern void mach_prepare_reboot(void);
>  extern void mach_prepare_shutdown(void);
>  
>  /* environment arguments from bootloader */
> -extern unsigned long cpu_clock_freq;
> -extern unsigned long memsize, highmemsize;
> +extern u32 cpu_clock_freq;
> +extern u32 memsize, highmemsize;
>  
>  /* loongson-specific command line, env and memory initialization */
>  extern void __init prom_init_memory(void);
> diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
> index 0a18fcf..ba2b6df 100644
> --- a/arch/mips/loongson/common/env.c
> +++ b/arch/mips/loongson/common/env.c
> @@ -18,29 +18,37 @@
>   * option) any later version.
>   */
>  #include <linux/module.h>
> -
>  #include <asm/bootinfo.h>
> -
>  #include <loongson.h>
> +#include <boot_param.h>
> +
> +struct boot_params *boot_p;
> +struct loongson_params *loongson_p;
> +
> +struct efi_cpuinfo_loongson *ecpu;
> +struct efi_memory_map_loongson *emap;
> +struct system_loongson *esys;
> +struct irq_source_routing_table *eirq_source;
> +struct loongson_system_configuration loongson_sysconf;
>  
> -unsigned long cpu_clock_freq;
> +u32 cpu_clock_freq;
>  EXPORT_SYMBOL(cpu_clock_freq);
> -unsigned long memsize, highmemsize;
>  
>  #define parse_even_earlier(res, option, p)				\
>  do {									\
>  	unsigned int tmp __maybe_unused;				\
>  									\
>  	if (strncmp(option, (char *)p, strlen(option)) == 0)		\
> -		tmp = strict_strtol((char *)p + strlen(option"="), 10, &res); \
> +		tmp = kstrtou32((char *)p + strlen(option"="), 10, &res); \
>  } while (0)
>  
>  void __init prom_init_env(void)
>  {
>  	/* pmon passes arguments in 32bit pointers */
> -	int *_prom_envp;
> -	unsigned long bus_clock;
>  	unsigned int processor_id;
> +
> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
> +	int *_prom_envp;
>  	long l;
>  
>  	/* firmware arguments are initialized in head.S */
> @@ -48,7 +56,6 @@ void __init prom_init_env(void)
>  
>  	l = (long)*_prom_envp;
>  	while (l != 0) {
> -		parse_even_earlier(bus_clock, "busclock", l);
>  		parse_even_earlier(cpu_clock_freq, "cpuclock", l);
>  		parse_even_earlier(memsize, "memsize", l);
>  		parse_even_earlier(highmemsize, "highmemsize", l);
> @@ -57,8 +64,38 @@ void __init prom_init_env(void)
>  	}
>  	if (memsize == 0)
>  		memsize = 256;
> -	if (bus_clock == 0)
> -		bus_clock = 66000000;
> +	pr_info("memsize=%ld, highmemsize=%ld\n", memsize, highmemsize);
> +#else
> +	/* firmware arguments are initialized in head.S */
> +	boot_p = (struct boot_params *)fw_arg2;
> +	loongson_p = &(boot_p->efi.smbios.lp);
> +
> +	ecpu = (struct efi_cpuinfo_loongson *)
> +		((u64)loongson_p + loongson_p->cpu_offset);
> +	emap = (struct efi_memory_map_loongson *)
> +		((u64)loongson_p + loongson_p->memory_offset);
> +	eirq_source = (struct irq_source_routing_table *)
> +		((u64)loongson_p + loongson_p->irq_offset);
> +
> +	cpu_clock_freq = ecpu->cpu_clock_freq;
> +	loongson_sysconf.cputype = ecpu->cputype;
> +	loongson_sysconf.nr_cpus = ecpu->nr_cpus;
> +	if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
> +		loongson_sysconf.nr_cpus = NR_CPUS;
> +
> +	loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr;
> +	loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
> +	loongson_sysconf.pci_io_base = eirq_source->pci_io_start_addr;
> +
> +	loongson_sysconf.restart_addr = boot_p->reset_system.ResetWarm;
> +	loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
> +
> +	loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
> +	loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios;
> +	pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
> +		loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
> +		loongson_sysconf.vgabios_addr);
> +#endif
>  	if (cpu_clock_freq == 0) {
>  		processor_id = (&current_cpu_data)->processor_id;
>  		switch (processor_id & PRID_REV_MASK) {
> @@ -68,12 +105,13 @@ void __init prom_init_env(void)
>  		case PRID_REV_LOONGSON2F:
>  			cpu_clock_freq = 797000000;
>  			break;
> +		case PRID_REV_LOONGSON3A:
> +			cpu_clock_freq = 900000000;
> +			break;
>  		default:
>  			cpu_clock_freq = 100000000;
>  			break;
>  		}
>  	}
> -
> -	pr_info("busclock=%ld, cpuclock=%ld, memsize=%ld, highmemsize=%ld\n",
> -		bus_clock, cpu_clock_freq, memsize, highmemsize);
> +	pr_info("CpuClock = %u\n", cpu_clock_freq);
>  }
> diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
> index ae7af1f..81ba3b4 100644
> --- a/arch/mips/loongson/common/init.c
> +++ b/arch/mips/loongson/common/init.c
> @@ -17,10 +17,6 @@ unsigned long __maybe_unused _loongson_addrwincfg_base;
>  
>  void __init prom_init(void)
>  {
> -	/* init base address of io space */
> -	set_io_port_base((unsigned long)
> -		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
> -
>  #ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
>  	_loongson_addrwincfg_base = (unsigned long)
>  		ioremap(LOONGSON_ADDRWINCFG_BASE, LOONGSON_ADDRWINCFG_SIZE);
> @@ -28,6 +24,11 @@ void __init prom_init(void)
>  
>  	prom_init_cmdline();
>  	prom_init_env();
> +
> +	/* init base address of io space */
> +	set_io_port_base((unsigned long)
> +		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
> +
>  	prom_init_memory();
>  
>  	/*init the uart base address */
> diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c
> index 8626a42..42b2431 100644
> --- a/arch/mips/loongson/common/mem.c
> +++ b/arch/mips/loongson/common/mem.c
> @@ -11,9 +11,14 @@
>  #include <asm/bootinfo.h>
>  
>  #include <loongson.h>
> +#include <boot_param.h>
>  #include <mem.h>
>  #include <pci.h>
>  
> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
> +
> +u32 memsize, highmemsize;
> +
>  void __init prom_init_memory(void)
>  {
>  	add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
> @@ -49,6 +54,43 @@ void __init prom_init_memory(void)
>  #endif /* !CONFIG_64BIT */
>  }
>  
> +#else /* CONFIG_LEFI_FIRMWARE_INTERFACE */
> +
> +void __init prom_init_memory(void)
> +{
> +	int i;
> +	u32 node_id;
> +	u32 mem_type;
> +
> +	/* parse memory information */
> +	for (i = 0; i < emap->nr_map; i++) {
> +		node_id = emap->map[i].node_id;
> +		mem_type = emap->map[i].mem_type;
> +
> +		if (node_id == 0) {
> +			switch (mem_type) {
> +			case SYSTEM_RAM_LOW:
> +				add_memory_region(emap->map[i].mem_start,
> +					(u64)emap->map[i].mem_size << 20,
> +					BOOT_MEM_RAM);
> +				break;
> +			case SYSTEM_RAM_HIGH:
> +				add_memory_region(emap->map[i].mem_start,
> +					(u64)emap->map[i].mem_size << 20,
> +					BOOT_MEM_RAM);
> +				break;
> +			case MEM_RESERVED:
> +				add_memory_region(emap->map[i].mem_start,
> +					(u64)emap->map[i].mem_size << 20,
> +					BOOT_MEM_RESERVED);
> +				break;
> +			}
> +		}
> +	}
> +}
> +
> +#endif /* CONFIG_LEFI_FIRMWARE_INTERFACE */
> +
>  /* override of arch/mips/mm/cache.c: __uncached_access */
>  int __uncached_access(struct file *file, unsigned long addr)
>  {
> diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson/common/pci.c
> index fa77844..003ab4e 100644
> --- a/arch/mips/loongson/common/pci.c
> +++ b/arch/mips/loongson/common/pci.c
> @@ -11,6 +11,7 @@
>  
>  #include <pci.h>
>  #include <loongson.h>
> +#include <boot_param.h>
>  
>  static struct resource loongson_pci_mem_resource = {
>  	.name	= "pci memory space",
> @@ -82,7 +83,10 @@ static int __init pcibios_init(void)
>  	setup_pcimap();
>  
>  	loongson_pci_controller.io_map_base = mips_io_port_base;
> -
> +#ifdef CONFIG_LEFI_FIRMWARE_INTERFACE
> +	loongson_pci_mem_resource.start = loongson_sysconf.pci_mem_start_addr;
> +	loongson_pci_mem_resource.end = loongson_sysconf.pci_mem_end_addr;
> +#endif
>  	register_pci_controller(&loongson_pci_controller);
>  
>  	return 0;
> diff --git a/arch/mips/loongson/common/reset.c b/arch/mips/loongson/common/reset.c
> index 65bfbb5..a60715e 100644
> --- a/arch/mips/loongson/common/reset.c
> +++ b/arch/mips/loongson/common/reset.c
> @@ -16,6 +16,7 @@
>  #include <asm/reboot.h>
>  
>  #include <loongson.h>
> +#include <boot_param.h>
>  
>  static inline void loongson_reboot(void)
>  {
> @@ -37,17 +38,37 @@ static inline void loongson_reboot(void)
>  
>  static void loongson_restart(char *command)
>  {
> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
>  	/* do preparation for reboot */
>  	mach_prepare_reboot();
>  
>  	/* reboot via jumping to boot base address */
>  	loongson_reboot();
> +#else
> +	void (*fw_restart)(void) = (void *)loongson_sysconf.restart_addr;
> +
> +	fw_restart();
> +	while (1) {
> +		if (cpu_wait)
> +			cpu_wait();
> +	}
> +#endif
>  }
>  
>  static void loongson_poweroff(void)
>  {
> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
>  	mach_prepare_shutdown();
>  	unreachable();
> +#else
> +	void (*fw_poweroff)(void) = (void *)loongson_sysconf.poweroff_addr;
> +
> +	fw_poweroff();
> +	while (1) {
> +		if (cpu_wait)
> +			cpu_wait();
> +	}
> +#endif
>  }
>  
>  static void loongson_halt(void)
> -- 
> 1.7.7.3
> 
> 

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 05/12] MIPS: Loongson 3: Add HT-linked PCI support
  2014-01-08  2:44 ` [PATCH V16 05/12] MIPS: Loongson 3: Add HT-linked PCI support Huacai Chen
@ 2014-01-08 22:58   ` Aurelien Jarno
       [not found]     ` <CAAhV-H57tDmYByjVwhf3teFZkGowR4E9+OO1vO0kP3iAKTNJVw@mail.gmail.com>
  0 siblings, 1 reply; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-08 22:58 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Wed, Jan 08, 2014 at 10:44:21AM +0800, Huacai Chen wrote:
> Loongson family machines use Hyper-Transport bus for inter-core
> connection and device connection. The PCI bus is a subordinate
> linked at HT1.
> 
> With LEFI firmware interface, We don't need fixup for PCI irq routing
> (except providing a VBIOS of the integrated GPU).
> 
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>  arch/mips/include/asm/mach-loongson/loongson.h |    7 ++
>  arch/mips/include/asm/mach-loongson/pci.h      |    5 +
>  arch/mips/pci/Makefile                         |    1 +
>  arch/mips/pci/fixup-loongson3.c                |   70 ++++++++++++++++
>  arch/mips/pci/ops-loongson3.c                  |  101 ++++++++++++++++++++++++
>  5 files changed, 184 insertions(+), 0 deletions(-)
>  create mode 100644 arch/mips/pci/fixup-loongson3.c
>  create mode 100644 arch/mips/pci/ops-loongson3.c
> 
> diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
> index 5913ea0..f0367ff 100644
> --- a/arch/mips/include/asm/mach-loongson/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson/loongson.h
> @@ -15,6 +15,7 @@
>  #include <linux/init.h>
>  #include <linux/irq.h>
>  #include <linux/kconfig.h>
> +#include <boot_param.h>
>  
>  /* loongson internal northbridge initialization */
>  extern void bonito_irq_init(void);
> @@ -101,7 +102,13 @@ static inline void do_perfcnt_IRQ(void)
>  #define LOONGSON_PCICFG_BASE	0x1fe80000
>  #define LOONGSON_PCICFG_SIZE	0x00000800	/* 2K */
>  #define LOONGSON_PCICFG_TOP	(LOONGSON_PCICFG_BASE+LOONGSON_PCICFG_SIZE-1)
> +
> +#if defined(CONFIG_HT_PCI)
> +#define LOONGSON_PCIIO_BASE	loongson_sysconf.pci_io_base
> +#else
>  #define LOONGSON_PCIIO_BASE	0x1fd00000

If CONFIG_HT_PCI, it will use address 0x1fd00000. Does it have a chance
to work on Loongson 3?

> +#endif
> +
>  #define LOONGSON_PCIIO_SIZE	0x00100000	/* 1M */
>  #define LOONGSON_PCIIO_TOP	(LOONGSON_PCIIO_BASE+LOONGSON_PCIIO_SIZE-1)
>  
> diff --git a/arch/mips/include/asm/mach-loongson/pci.h b/arch/mips/include/asm/mach-loongson/pci.h
> index bc99dab..1212774 100644
> --- a/arch/mips/include/asm/mach-loongson/pci.h
> +++ b/arch/mips/include/asm/mach-loongson/pci.h
> @@ -40,8 +40,13 @@ extern struct pci_ops loongson_pci_ops;
>  #else	/* loongson2f/32bit & loongson2e */
>  
>  /* this pci memory space is mapped by pcimap in pci.c */
> +#ifdef CONFIG_CPU_LOONGSON3
> +#define LOONGSON_PCI_MEM_START	0x40000000UL
> +#define LOONGSON_PCI_MEM_END	0x7effffffUL
> +#else
>  #define LOONGSON_PCI_MEM_START	LOONGSON_PCILO1_BASE
>  #define LOONGSON_PCI_MEM_END	(LOONGSON_PCILO1_BASE + 0x04000000 * 2)
> +#endif
>  /* this is an offset from mips_io_port_base */
>  #define LOONGSON_PCI_IO_START	0x00004000UL
>  
> diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
> index 719e455..5475859 100644
> --- a/arch/mips/pci/Makefile
> +++ b/arch/mips/pci/Makefile
> @@ -29,6 +29,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_LEMOTE_MACH3A)	+= fixup-loongson3.o ops-loongson3.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/fixup-loongson3.c b/arch/mips/pci/fixup-loongson3.c
> new file mode 100644
> index 0000000..4a8477d
> --- /dev/null
> +++ b/arch/mips/pci/fixup-loongson3.c
> @@ -0,0 +1,70 @@
> +/*
> + * fixup-loongson3.c
> + *
> + * Copyright (C) 2012 Lemote, Inc.
> + * Author: Xiang Yu, xiangy@lemote.com
> + *         Chen Huacai, chenhc@lemote.com
> + *
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + *
> + * THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
> + * WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
> + * NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
> + * USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
> + * ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + *
> + * You should have received a copy of the  GNU General Public License along
> + * with this program; if not, write  to the Free Software Foundation, Inc.,
> + * 675 Mass Ave, Cambridge, MA 02139, USA.

checkpatch.pl reports that the address is wrong, and it is correct. As
suggested the best option is to just remove the three lines above.

> + *
> + */
> +
> +#include <linux/pci.h>
> +#include <boot_param.h>
> +
> +static void print_fixup_info(const struct pci_dev *pdev)
> +{
> +	dev_info(&pdev->dev, "Device %x:%x, irq %d\n",
> +			pdev->vendor, pdev->device, pdev->irq);
> +}
> +
> +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> +{
> +	print_fixup_info(dev);
> +	return dev->irq;
> +}
> +
> +static void pci_fixup_radeon(struct pci_dev *pdev)
> +{
> +	if (pdev->resource[PCI_ROM_RESOURCE].start)
> +		return;
> +
> +	if (!loongson_sysconf.vgabios_addr)
> +		return;
> +
> +	pdev->resource[PCI_ROM_RESOURCE].start =
> +		loongson_sysconf.vgabios_addr;
> +	pdev->resource[PCI_ROM_RESOURCE].end   =
> +		loongson_sysconf.vgabios_addr + 256*1024 - 1;
> +	pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_COPY;
> +
> +	dev_info(&pdev->dev, "BAR %d: assigned %pR for Radeon ROM\n",
> +			PCI_ROM_RESOURCE, &pdev->resource[PCI_ROM_RESOURCE]);
> +}
> +
> +DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
> +				PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_radeon);
> +
> +/* Do platform specific device initialization at pci_enable_device() time */
> +int pcibios_plat_dev_init(struct pci_dev *dev)
> +{
> +	return 0;
> +}
> diff --git a/arch/mips/pci/ops-loongson3.c b/arch/mips/pci/ops-loongson3.c
> new file mode 100644
> index 0000000..077eafa
> --- /dev/null
> +++ b/arch/mips/pci/ops-loongson3.c
> @@ -0,0 +1,101 @@
> +#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
> +
> +static int loongson3_pci_config_access(unsigned char access_type,
> +		struct pci_bus *bus, unsigned int devfn,
> +		int where, u32 *data)
> +{
> +	unsigned char busnum = bus->number;
> +	u_int64_t addr, type;
> +	void *addrp;
> +	int device = PCI_SLOT(devfn);
> +	int function = PCI_FUNC(devfn);
> +	int reg = where & ~3;
> +
> +	addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
> +	if (busnum == 0) {
> +		if (device > 31)
> +			return PCIBIOS_DEVICE_NOT_FOUND;
> +		addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE) | (addr & 0xffff));
> +		type = 0;
> +
> +	} else {
> +		addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE_TP1) | (addr));
> +		type = 0x10000;
> +	}
> +
> +	if (access_type == PCI_ACCESS_WRITE)
> +		writel(cpu_to_le32(*data), addrp);

writel already includes the call to cpu_to_le32, so it can be written
directly as:

	writel(*data) addrp);

As cpu_to_le32 is a no-op on little endian, both work, but it is not
correct to use cpu_to_le32 here.

> +	else {
> +		*data = le32_to_cpu(readl(addrp));


Same here, this should be written as :
	
	*data = readl(addrp);

> +		if (*data == 0xffffffff) {
> +			*data = -1;
> +			return PCIBIOS_DEVICE_NOT_FOUND;
> +		}
> +	}
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int loongson3_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn,
> +				 int where, int size, u32 *val)
> +{
> +	u32 data = 0;
> +	int ret = loongson3_pci_config_access(PCI_ACCESS_READ,
> +			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 loongson3_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn,
> +				  int where, int size, u32 val)
> +{
> +	u32 data = 0;
> +	int ret;
> +
> +	if (size == 4)
> +		data = val;
> +	else {
> +		ret = loongson3_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 = loongson3_pci_config_access(PCI_ACCESS_WRITE,
> +			bus, devfn, where, &data);
> +
> +	return ret;
> +}
> +
> +struct pci_ops loongson_pci_ops = {
> +	.read = loongson3_pci_pcibios_read,
> +	.write = loongson3_pci_pcibios_write
> +};
> -- 
> 1.7.7.3
> 
> 

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 06/12] MIPS: Loongson 3: Add IRQ init and dispatch support
  2014-01-08  2:44 ` [PATCH V16 06/12] MIPS: Loongson 3: Add IRQ init and dispatch support Huacai Chen
@ 2014-01-08 22:58   ` Aurelien Jarno
  2014-01-09 12:52     ` Alex Smith
  1 sibling, 0 replies; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-08 22:58 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Wed, Jan 08, 2014 at 10:44:22AM +0800, Huacai Chen wrote:
> IRQ routing path of Loongson-3:
> Devices(most) --> I8259 --> HT Controller --> IRQ Routing Table --> CPU
>                                                   ^
>                                                   |
> Device(legacy devices such as UART) --> Bonito ---|
> 
> IRQ Routing Table route 32 INTs to CPU's INT0~INT3(IP2~IP5 of CP0), 32
> INTs include 16 HT INTs(mostly), 4 PCI INTs, 1 LPC INT, etc. IP6 is used
> for IPI and IP7 is used for internal MIPS timer. LOONGSON_INT_ROUTER_*
> are IRQ Routing Table registers.
> 
> I8259 IRQs are 1:1 mapped to HT1 INTs. LOONGSON_HT1_* are configuration
> registers of HT1 controller.
> 
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>  arch/mips/include/asm/mach-loongson/irq.h      |   26 ++++++
>  arch/mips/include/asm/mach-loongson/loongson.h |   10 ++
>  arch/mips/loongson/Makefile                    |    6 ++
>  arch/mips/loongson/loongson-3/Makefile         |    4 +
>  arch/mips/loongson/loongson-3/irq.c            |  110 ++++++++++++++++++++++++
>  5 files changed, 156 insertions(+), 0 deletions(-)
>  create mode 100644 arch/mips/include/asm/mach-loongson/irq.h
>  create mode 100644 arch/mips/loongson/loongson-3/Makefile
>  create mode 100644 arch/mips/loongson/loongson-3/irq.c
> 
> diff --git a/arch/mips/include/asm/mach-loongson/irq.h b/arch/mips/include/asm/mach-loongson/irq.h
> new file mode 100644
> index 0000000..5711e3b
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson/irq.h
> @@ -0,0 +1,26 @@
> +#ifndef __ASM_MACH_LOONGSON_IRQ_H_
> +#define __ASM_MACH_LOONGSON_IRQ_H_
> +
> +#include <boot_param.h>
> +
> +/* cpu core interrupt numbers */
> +#define MIPS_CPU_IRQ_BASE 56
> +
> +#ifdef CONFIG_CPU_LOONGSON3
> +
> +#define LOONGSON_UART_IRQ   (MIPS_CPU_IRQ_BASE + 2) /* UART */
> +#define LOONGSON_HT1_IRQ    (MIPS_CPU_IRQ_BASE + 3) /* HT1 */
> +#define LOONGSON_TIMER_IRQ  (MIPS_CPU_IRQ_BASE + 7) /* CPU Timer */
> +
> +#define LOONGSON_HT1_CFG_BASE		loongson_sysconf.ht_control_base
> +#define LOONGSON_HT1_INT_VECTOR_BASE	(LOONGSON_HT1_CFG_BASE + 0x80)
> +#define LOONGSON_HT1_INT_EN_BASE	(LOONGSON_HT1_CFG_BASE + 0xa0)
> +#define LOONGSON_HT1_INT_VECTOR(n)	\
> +		LOONGSON3_REG32(LOONGSON_HT1_INT_VECTOR_BASE, 4 * n)
> +#define LOONGSON_HT1_INTN_EN(n)		\
> +		LOONGSON3_REG32(LOONGSON_HT1_INT_EN_BASE, 4 * n)
> +
> +#endif
> +
> +#include_next <irq.h>
> +#endif /* __ASM_MACH_LOONGSON_IRQ_H_ */
> diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
> index f0367ff..69e9d9e 100644
> --- a/arch/mips/include/asm/mach-loongson/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson/loongson.h
> @@ -62,6 +62,12 @@ extern int mach_i8259_irq(void);
>  #define LOONGSON_REG(x) \
>  	(*(volatile u32 *)((char *)CKSEG1ADDR(LOONGSON_REG_BASE) + (x)))
>  
> +#define LOONGSON3_REG8(base, x) \
> +	(*(volatile u8 *)((char *)TO_UNCAC(base) + (x)))
> +
> +#define LOONGSON3_REG32(base, x) \
> +	(*(volatile u32 *)((char *)TO_UNCAC(base) + (x)))
> +
>  #define LOONGSON_IRQ_BASE	32
>  #define LOONGSON2_PERFCNT_IRQ	(MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */
>  
> @@ -87,6 +93,10 @@ static inline void do_perfcnt_IRQ(void)
>  #define LOONGSON_REG_BASE	0x1fe00000
>  #define LOONGSON_REG_SIZE	0x00100000	/* 256Bytes + 256Bytes + ??? */
>  #define LOONGSON_REG_TOP	(LOONGSON_REG_BASE+LOONGSON_REG_SIZE-1)
> +/* Loongson-3 specific registers */
> +#define LOONGSON3_REG_BASE	0x3ff00000
> +#define LOONGSON3_REG_SIZE	0x00100000	/* 256Bytes + 256Bytes + ??? */
> +#define LOONGSON3_REG_TOP	(LOONGSON3_REG_BASE+LOONGSON3_REG_SIZE-1)
>  
>  #define LOONGSON_LIO1_BASE	0x1ff00000
>  #define LOONGSON_LIO1_SIZE	0x00100000	/* 1M */
> diff --git a/arch/mips/loongson/Makefile b/arch/mips/loongson/Makefile
> index 0dc0055..7429994 100644
> --- a/arch/mips/loongson/Makefile
> +++ b/arch/mips/loongson/Makefile
> @@ -15,3 +15,9 @@ obj-$(CONFIG_LEMOTE_FULOONG2E)	+= fuloong-2e/
>  #
>  
>  obj-$(CONFIG_LEMOTE_MACH2F)  += lemote-2f/
> +
> +#
> +# All Loongson-3 family machines
> +#
> +
> +obj-$(CONFIG_CPU_LOONGSON3)  += loongson-3/
> diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
> new file mode 100644
> index 0000000..b9968cd
> --- /dev/null
> +++ b/arch/mips/loongson/loongson-3/Makefile
> @@ -0,0 +1,4 @@
> +#
> +# Makefile for Loongson-3 family machines
> +#
> +obj-y			+= irq.o
> diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
> new file mode 100644
> index 0000000..3b52d56
> --- /dev/null
> +++ b/arch/mips/loongson/loongson-3/irq.c
> @@ -0,0 +1,110 @@
> +#include <loongson.h>
> +#include <irq.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +
> +#include <asm/irq_cpu.h>
> +#include <asm/i8259.h>
> +#include <asm/mipsregs.h>
> +
> +#define LOONGSON_INT_ROUTER_OFFSET	0x1400
> +#define LOONGSON_INT_ROUTER_INTEN	\
> +	  LOONGSON3_REG32(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + 0x24)
> +#define LOONGSON_INT_ROUTER_INTENSET	\
> +	  LOONGSON3_REG32(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + 0x28)
> +#define LOONGSON_INT_ROUTER_INTENCLR	\
> +	  LOONGSON3_REG32(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + 0x2c)
> +#define LOONGSON_INT_ROUTER_ENTRY(n)	\
> +	  LOONGSON3_REG8(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + n)
> +#define LOONGSON_INT_ROUTER_LPC		LOONGSON_INT_ROUTER_ENTRY(0x0a)
> +#define LOONGSON_INT_ROUTER_HT1(n)	LOONGSON_INT_ROUTER_ENTRY(n + 0x18)
> +
> +#define LOONGSON_INT_CORE0_INT0		0x11 /* route to int 0 of core 0 */
> +#define LOONGSON_INT_CORE0_INT1		0x21 /* route to int 1 of core 0 */
> +
> +static void ht_irqdispatch(void)
> +{
> +	unsigned int i, irq;
> +	unsigned int ht_irq[] = {1, 3, 4, 5, 6, 7, 8, 12, 14, 15};
> +
> +	irq = LOONGSON_HT1_INT_VECTOR(0);
> +	LOONGSON_HT1_INT_VECTOR(0) = irq; /* Acknowledge the IRQs */
> +
> +	for (i = 0; i < (sizeof(ht_irq) / sizeof(*ht_irq)); i++) {
> +		if (irq & (0x1 << ht_irq[i]))
> +			do_IRQ(ht_irq[i]);
> +	}
> +}
> +
> +void mach_irq_dispatch(unsigned int pending)
> +{
> +	if (pending & CAUSEF_IP7)
> +		do_IRQ(LOONGSON_TIMER_IRQ);
> +	else if (pending & CAUSEF_IP3)
> +		ht_irqdispatch();
> +	else if (pending & CAUSEF_IP2)
> +		do_IRQ(LOONGSON_UART_IRQ);
> +	else {
> +		pr_err("%s : spurious interrupt\n", __func__);
> +		spurious_interrupt();
> +	}
> +}
> +
> +static struct irqaction cascade_irqaction = {
> +	.handler = no_action,
> +	.name = "cascade",
> +};
> +
> +static inline void mask_loongson_irq(struct irq_data *d)
> +{
> +	clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
> +	irq_disable_hazard();
> +}
> +
> +static inline void unmask_loongson_irq(struct irq_data *d)
> +{
> +	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
> +	irq_enable_hazard();
> +}
> +
> + /* For MIPS IRQs which shared by all cores */
> +static struct irq_chip loongson_irq_chip = {
> +	.name		= "Loongson",
> +	.irq_ack	= mask_loongson_irq,
> +	.irq_mask	= mask_loongson_irq,
> +	.irq_mask_ack	= mask_loongson_irq,
> +	.irq_unmask	= unmask_loongson_irq,
> +	.irq_eoi	= unmask_loongson_irq,
> +};
> +
> +void irq_router_init(void)
> +{
> +	int i;
> +
> +	/* route LPC int to cpu core0 int 0 */
> +	LOONGSON_INT_ROUTER_LPC = LOONGSON_INT_CORE0_INT0;
> +	/* route HT1 int0 ~ int7 to cpu core0 INT1*/
> +	for (i = 0; i < 8; i++)
> +		LOONGSON_INT_ROUTER_HT1(i) = LOONGSON_INT_CORE0_INT1;
> +	/* enable HT1 interrupt */
> +	LOONGSON_HT1_INTN_EN(0) = 0xffffffff;
> +	/* enable router interrupt intenset */
> +	LOONGSON_INT_ROUTER_INTENSET =
> +		LOONGSON_INT_ROUTER_INTEN | (0xffff << 16) | 0x1 << 10;
> +}
> +
> +void __init mach_init_irq(void)
> +{
> +	clear_c0_status(ST0_IM | ST0_BEV);
> +
> +	irq_router_init();
> +	mips_cpu_irq_init();
> +	init_i8259_irqs();
> +	irq_set_chip_and_handler(LOONGSON_UART_IRQ,
> +			&loongson_irq_chip, handle_level_irq);
> +
> +	/* setup HT1 irq */
> +	setup_irq(LOONGSON_HT1_IRQ, &cascade_irqaction);
> +
> +	set_c0_status(STATUSF_IP2 | STATUSF_IP6);
> +}

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 07/12] MIPS: Loongson 3: Add serial port support
  2014-01-08  2:44 ` [PATCH V16 07/12] MIPS: Loongson 3: Add serial port support Huacai Chen
@ 2014-01-08 22:58   ` Aurelien Jarno
  0 siblings, 0 replies; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-08 22:58 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Wed, Jan 08, 2014 at 10:44:23AM +0800, Huacai Chen wrote:
> Loongson family machines has three types of serial port: PCI UART, LPC
> UART and CPU internal UART. Loongson-2E and parts of Loongson-2F based
> machines use PCI UART; most Loongson-2F based machines use LPC UART;
> Loongson-2G/3A has both LPC and CPU UART but usually use CPU UART.
> 
> Port address of UARTs:
> CPU UART: REG_BASE + OFFSET;
> LPC UART: LIO1_BASE + OFFSET;
> PCI UART: PCIIO_BASE + OFFSET.
> 
> Since LPC UART are linked in "Local Bus", both CPU UART and LPC UART
> are called "CPU provided serial port".
> 
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>  arch/mips/loongson/common/serial.c    |   26 +++++++++++++++-----------
>  arch/mips/loongson/common/uart_base.c |    9 ++++++++-
>  2 files changed, 23 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/mips/loongson/common/serial.c b/arch/mips/loongson/common/serial.c
> index 5f2b78a..bd2b709 100644
> --- a/arch/mips/loongson/common/serial.c
> +++ b/arch/mips/loongson/common/serial.c
> @@ -19,19 +19,19 @@
>  #include <loongson.h>
>  #include <machine.h>
>  
> -#define PORT(int)			\
> +#define PORT(int, clk)			\
>  {								\
>  	.irq		= int,					\
> -	.uartclk	= 1843200,				\
> +	.uartclk	= clk,					\
>  	.iotype		= UPIO_PORT,				\
>  	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,	\
>  	.regshift	= 0,					\
>  }
>  
> -#define PORT_M(int)				\
> +#define PORT_M(int, clk)				\
>  {								\
>  	.irq		= MIPS_CPU_IRQ_BASE + (int),		\
> -	.uartclk	= 3686400,				\
> +	.uartclk	= clk,					\
>  	.iotype		= UPIO_MEM,				\
>  	.membase	= (void __iomem *)NULL,			\
>  	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,	\
> @@ -40,13 +40,17 @@
>  
>  static struct plat_serial8250_port uart8250_data[][2] = {
>  	[MACH_LOONGSON_UNKNOWN]		{},
> -	[MACH_LEMOTE_FL2E]		{PORT(4), {} },
> -	[MACH_LEMOTE_FL2F]		{PORT(3), {} },
> -	[MACH_LEMOTE_ML2F7]		{PORT_M(3), {} },
> -	[MACH_LEMOTE_YL2F89]		{PORT_M(3), {} },
> -	[MACH_DEXXON_GDIUM2F10]		{PORT_M(3), {} },
> -	[MACH_LEMOTE_NAS]		{PORT_M(3), {} },
> -	[MACH_LEMOTE_LL2F]		{PORT(3), {} },
> +	[MACH_LEMOTE_FL2E]              {PORT(4, 1843200), {} },
> +	[MACH_LEMOTE_FL2F]              {PORT(3, 1843200), {} },
> +	[MACH_LEMOTE_ML2F7]             {PORT_M(3, 3686400), {} },
> +	[MACH_LEMOTE_YL2F89]            {PORT_M(3, 3686400), {} },
> +	[MACH_DEXXON_GDIUM2F10]         {PORT_M(3, 3686400), {} },
> +	[MACH_LEMOTE_NAS]               {PORT_M(3, 3686400), {} },
> +	[MACH_LEMOTE_LL2F]              {PORT(3, 1843200), {} },
> +	[MACH_LEMOTE_A1004]             {PORT_M(2, 33177600), {} },
> +	[MACH_LEMOTE_A1101]             {PORT_M(2, 25000000), {} },
> +	[MACH_LEMOTE_A1201]             {PORT_M(2, 25000000), {} },
> +	[MACH_LEMOTE_A1205]             {PORT_M(2, 25000000), {} },
>  	[MACH_LOONGSON_END]		{},
>  };
>  
> diff --git a/arch/mips/loongson/common/uart_base.c b/arch/mips/loongson/common/uart_base.c
> index e192ad0..1e1eeea 100644
> --- a/arch/mips/loongson/common/uart_base.c
> +++ b/arch/mips/loongson/common/uart_base.c
> @@ -35,9 +35,16 @@ void prom_init_loongson_uart_base(void)
>  	case MACH_DEXXON_GDIUM2F10:
>  	case MACH_LEMOTE_NAS:
>  	default:
> -		/* The CPU provided serial port */
> +		/* The CPU provided serial port (LPC) */
>  		loongson_uart_base = LOONGSON_LIO1_BASE + 0x3f8;
>  		break;
> +	case MACH_LEMOTE_A1004:
> +	case MACH_LEMOTE_A1101:
> +	case MACH_LEMOTE_A1201:
> +	case MACH_LEMOTE_A1205:
> +		/* The CPU provided serial port (CPU) */
> +		loongson_uart_base = LOONGSON_REG_BASE + 0x1e0;
> +		break;
>  	}
>  
>  	_loongson_uart_base =

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 08/12] MIPS: Loongson: Add swiotlb to support big memory (>4GB)
  2014-01-08  2:44 ` [PATCH V16 08/12] MIPS: Loongson: Add swiotlb to support big memory (>4GB) Huacai Chen
@ 2014-01-08 22:58   ` Aurelien Jarno
       [not found]     ` <CAAhV-H4h43N2OR4znwVv3miVbGkWJLapdgr9Jou1j4R8-9TRyA@mail.gmail.com>
  2014-01-09 12:56     ` Alex Smith
  1 sibling, 1 reply; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-08 22:58 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Wed, Jan 08, 2014 at 10:44:24AM +0800, Huacai Chen wrote:
> This is probably a workaround because Loongson doesn't support DMA
> address above 4GB. If memory is more than 4GB, CONFIG_SWIOTLB and
> ZONE_DMA32 should be selected. In this way, DMA pages are allocated
> below 4GB preferably.
> 
> However, CONFIG_SWIOTLB+ZONE_DMA32 is not enough, so, we provide a
> platform-specific dma_map_ops::set_dma_mask() to make sure each
> driver's dma_mask and coherent_dma_mask is below 32-bit.
> 
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>  arch/mips/include/asm/dma-mapping.h                |    5 +
>  .../mips/include/asm/mach-loongson/dma-coherence.h |   22 +++-
>  arch/mips/loongson/common/Makefile                 |    5 +
>  arch/mips/loongson/common/dma-swiotlb.c            |  165 ++++++++++++++++++++
>  4 files changed, 196 insertions(+), 1 deletions(-)
>  create mode 100644 arch/mips/loongson/common/dma-swiotlb.c
> 
> diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
> index 84238c5..06412aa 100644
> --- a/arch/mips/include/asm/dma-mapping.h
> +++ b/arch/mips/include/asm/dma-mapping.h
> @@ -49,9 +49,14 @@ static inline int dma_mapping_error(struct device *dev, u64 mask)
>  static inline int
>  dma_set_mask(struct device *dev, u64 mask)
>  {
> +	struct dma_map_ops *ops = get_dma_ops(dev);
> +
>  	if(!dev->dma_mask || !dma_supported(dev, mask))
>  		return -EIO;
>  
> +	if (ops->set_dma_mask)
> +		return ops->set_dma_mask(dev, mask);
> +

I think that with the changes I propose in loongson_dma_alloc_coherent,
this should be useless.

>  	*dev->dma_mask = mask;
>  
>  	return 0;
> diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
> index aeb2c05..6a90275 100644
> --- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
> +++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
> @@ -11,24 +11,40 @@
>  #ifndef __ASM_MACH_LOONGSON_DMA_COHERENCE_H
>  #define __ASM_MACH_LOONGSON_DMA_COHERENCE_H
>  
> +#ifdef CONFIG_SWIOTLB
> +#include <linux/swiotlb.h>
> +#endif
> +
>  struct device;
>  
> +extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
> +extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
>  static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
>  					  size_t size)
>  {
> +#ifdef CONFIG_CPU_LOONGSON3
> +	return virt_to_phys(addr);
> +#else
>  	return virt_to_phys(addr) | 0x80000000;
> +#endif
>  }
>  
>  static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
>  					       struct page *page)
>  {
> +#ifdef CONFIG_CPU_LOONGSON3
> +	return page_to_phys(page);
> +#else
>  	return page_to_phys(page) | 0x80000000;
> +#endif
>  }
>  
>  static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
>  	dma_addr_t dma_addr)
>  {
> -#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
> +#if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT)
> +	return dma_addr;
> +#elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
>  	return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff);
>  #else
>  	return dma_addr & 0x7fffffff;
> @@ -55,7 +71,11 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
>  
>  static inline int plat_device_is_coherent(struct device *dev)
>  {
> +#ifdef CONFIG_DMA_NONCOHERENT
>  	return 0;
> +#else
> +	return 1;
> +#endif /* CONFIG_DMA_NONCOHERENT */
>  }
>  
>  #endif /* __ASM_MACH_LOONGSON_DMA_COHERENCE_H */
> diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile
> index 9e4484c..0bb9cc9 100644
> --- a/arch/mips/loongson/common/Makefile
> +++ b/arch/mips/loongson/common/Makefile
> @@ -26,3 +26,8 @@ obj-$(CONFIG_CS5536) += cs5536/
>  #
>  
>  obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
> +
> +#
> +# Big Memory (SWIOTLB) Support
> +#
> +obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o
> diff --git a/arch/mips/loongson/common/dma-swiotlb.c b/arch/mips/loongson/common/dma-swiotlb.c
> new file mode 100644
> index 0000000..9d5451b
> --- /dev/null
> +++ b/arch/mips/loongson/common/dma-swiotlb.c
> @@ -0,0 +1,165 @@
> +#include <linux/mm.h>
> +#include <linux/init.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/scatterlist.h>
> +#include <linux/swiotlb.h>
> +#include <linux/bootmem.h>
> +
> +#include <asm/bootinfo.h>
> +#include <dma-coherence.h>
> +
> +static void *loongson_dma_alloc_coherent(struct device *dev, size_t size,
> +		dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
> +{
> +	void *ret;
> +
> +	if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
> +		return ret;
> +
> +	/* ignore region specifiers */
> +	gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
> +
> +#ifdef CONFIG_ISA
> +	if (dev == NULL)
> +		gfp |= __GFP_DMA;
> +	else
> +#endif
> +#ifdef CONFIG_ZONE_DMA
> +	if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
> +		gfp |= __GFP_DMA;
> +	else
> +#endif
> +#ifdef CONFIG_ZONE_DMA32
> +	 /* Loongson-3 only support DMA in the memory below 4GB now */
> +	if (dev->coherent_dma_mask < DMA_BIT_MASK(40))

You don't want the if here. If the device has coherent_dma_mask with
the highest bit being the 32th one or higher, you still need
__GFP_DMA32 to make sure the memory will be allocated below 4GB, as
the Loongson 3 CPU doesn't support more than 32-bit DMA.

> +		gfp |= __GFP_DMA32;
> +	else
> +#endif
> +	;
> +	gfp |= __GFP_NORETRY;
> +
> +	ret = swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
> +	mb();
> +	return ret;
> +}
> +
> +static void loongson_dma_free_coherent(struct device *dev, size_t size,
> +		void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs)
> +{
> +	int order = get_order(size);
> +
> +	if (dma_release_from_coherent(dev, order, vaddr))
> +		return;
> +
> +	swiotlb_free_coherent(dev, size, vaddr, dma_handle);
> +}
> +
> +static dma_addr_t loongson_dma_map_page(struct device *dev, struct page *page,
> +				unsigned long offset, size_t size,
> +				enum dma_data_direction dir,
> +				struct dma_attrs *attrs)
> +{
> +	dma_addr_t daddr = swiotlb_map_page(dev, page, offset, size,
> +					dir, attrs);
> +	mb();
> +	return daddr;
> +}
> +
> +static int loongson_dma_map_sg(struct device *dev, struct scatterlist *sg,
> +				int nents, enum dma_data_direction dir,
> +				struct dma_attrs *attrs)
> +{
> +	int r = swiotlb_map_sg_attrs(dev, sg, nents, dir, NULL);
> +	mb();
> +
> +	return r;
> +}
> +
> +static void loongson_dma_sync_single_for_device(struct device *dev,
> +				dma_addr_t dma_handle, size_t size,
> +				enum dma_data_direction dir)
> +{
> +	swiotlb_sync_single_for_device(dev, dma_handle, size, dir);
> +	mb();
> +}
> +
> +static void loongson_dma_sync_sg_for_device(struct device *dev,
> +				struct scatterlist *sg, int nents,
> +				enum dma_data_direction dir)
> +{
> +	swiotlb_sync_sg_for_device(dev, sg, nents, dir);
> +	mb();
> +}
> +
> +static dma_addr_t
> +loongson_unity_phys_to_dma(struct device *dev, phys_addr_t paddr)
> +{
> +	return paddr;
> +}
> +
> +static phys_addr_t
> +loongson_unity_dma_to_phys(struct device *dev, dma_addr_t daddr)
> +{
> +	return daddr;
> +}
> +
> +struct loongson_dma_map_ops {
> +	struct dma_map_ops dma_map_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);
> +};
> +
> +dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
> +{
> +	struct loongson_dma_map_ops *ops = container_of(get_dma_ops(dev),
> +				struct loongson_dma_map_ops, dma_map_ops);
> +
> +	return ops->phys_to_dma(dev, paddr);
> +}
> +
> +phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
> +{
> +	struct loongson_dma_map_ops *ops = container_of(get_dma_ops(dev),
> +				struct loongson_dma_map_ops, dma_map_ops);
> +
> +	return ops->dma_to_phys(dev, daddr);
> +}
> +
> +static int loongson_dma_set_mask(struct device *dev, u64 mask)
> +{
> +	/* Loongson doesn't support DMA above 32-bit */
> +	if (mask > DMA_BIT_MASK(32)) {
> +		*dev->dma_mask = DMA_BIT_MASK(32);
> +		return -EIO;
> +	}
> +
> +	*dev->dma_mask = mask;
> +
> +	return 0;
> +}
> +
> +static struct loongson_dma_map_ops loongson_linear_dma_map_ops = {
> +	.dma_map_ops = {
> +		.alloc = loongson_dma_alloc_coherent,
> +		.free = loongson_dma_free_coherent,
> +		.map_page = loongson_dma_map_page,
> +		.unmap_page = swiotlb_unmap_page,
> +		.map_sg = loongson_dma_map_sg,
> +		.unmap_sg = swiotlb_unmap_sg_attrs,
> +		.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
> +		.sync_single_for_device = loongson_dma_sync_single_for_device,
> +		.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
> +		.sync_sg_for_device = loongson_dma_sync_sg_for_device,
> +		.mapping_error = swiotlb_dma_mapping_error,
> +		.dma_supported = swiotlb_dma_supported,
> +		.set_dma_mask = loongson_dma_set_mask
> +	},
> +	.phys_to_dma = loongson_unity_phys_to_dma,
> +	.dma_to_phys = loongson_unity_dma_to_phys
> +};
> +
> +void __init plat_swiotlb_setup(void)
> +{
> +	swiotlb_init(1);
> +	mips_dma_map_ops = &loongson_linear_dma_map_ops.dma_map_ops;
> +}

Thanks for the other changes, it now looks much better.


-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 04/12] MIPS: Loongson: Add UEFI-like firmware interface (LEFI) support
@ 2014-01-09 12:37     ` Alex Smith
  0 siblings, 0 replies; 55+ messages in thread
From: Alex Smith @ 2014-01-09 12:37 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, Aurelien Jarno,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

Hi,

On 08/01/14 02:44, Huacai Chen wrote:
> The new UEFI-like firmware interface (LEFI, i.e. Loongson Unified
> Firmware Interface) has 3 advantages:
>
> 1, Firmware export a physical memory map which is similar to X86's
>     E820 map, so prom_init_memory() will be more elegant that #ifdef
>     clauses can be removed.
> 2, Firmware export a pci irq routing table, we no longer need pci
>     irq routing fixup in kernel's code.
> 3, Firmware has a built-in vga bios, and its address is exported,
>     the linux kernel no longer need an embedded blob.
>
> With the LEFI interface, Loongson-3A/2G and all their successors can use
> a unified kernel. All Loongson-based machines support this new interface
> except 2E/2F series.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>   arch/mips/include/asm/mach-loongson/boot_param.h |  159 ++++++++++++++++++++++
>   arch/mips/include/asm/mach-loongson/loongson.h   |    4 +-
>   arch/mips/loongson/common/env.c                  |   64 +++++++--
>   arch/mips/loongson/common/init.c                 |    9 +-
>   arch/mips/loongson/common/mem.c                  |   42 ++++++
>   arch/mips/loongson/common/pci.c                  |    6 +-
>   arch/mips/loongson/common/reset.c                |   21 +++
>   7 files changed, 285 insertions(+), 20 deletions(-)
>   create mode 100644 arch/mips/include/asm/mach-loongson/boot_param.h
>
> diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h
> new file mode 100644
> index 0000000..234c0eb
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson/boot_param.h
> @@ -0,0 +1,159 @@
> +#ifndef __ASM_MACH_LOONGSON_BOOT_PARAM_H_
> +#define __ASM_MACH_LOONGSON_BOOT_PARAM_H_
> +
> +#define SYSTEM_RAM_LOW		1
> +#define SYSTEM_RAM_HIGH		2
> +#define MEM_RESERVED		3
> +#define PCI_IO			4
> +#define PCI_MEM			5
> +#define LOONGSON_CFG_REG	6
> +#define VIDEO_ROM		7
> +#define ADAPTER_ROM		8
> +#define ACPI_TABLE		9
> +#define MAX_MEMORY_TYPE		10
> +
> +#define LOONGSON3_BOOT_MEM_MAP_MAX 128
> +struct efi_memory_map_loongson {
> +	u16 vers;	/* version of efi_memory_map */
> +	u32 nr_map;	/* number of memory_maps */
> +	u32 mem_freq;	/* memory frequence */
> +	struct mem_map {
> +		u32 node_id;	/* node_id which memory attached to */
> +		u32 mem_type;	/* system memory, pci memory, pci io, etc. */
> +		u64 mem_start;	/* memory map start address */
> +		u32 mem_size;	/* each memory_map size, not the total size */
> +	} map[LOONGSON3_BOOT_MEM_MAP_MAX];
> +} __packed;
> +
> +enum loongson_cpu_type {
> +	Loongson_2E = 0,
> +	Loongson_2F = 1,
> +	Loongson_3A = 2,
> +	Loongson_3B = 3,
> +	Loongson_1A = 4,
> +	Loongson_1B = 5
> +};
> +
> +/*
> + * Capability and feature descriptor structure for MIPS CPU
> + */
> +struct efi_cpuinfo_loongson {
> +	u16 vers;     /* version of efi_cpuinfo_loongson */
> +	u32 processor_id; /* PRID, e.g. 6305, 6306 */
> +	u32 cputype;  /* Loongson_3A/3B, etc. */
> +	u32 total_node;   /* num of total numa nodes */
> +	u32 cpu_startup_core_id; /* Core id */
> +	u32 cpu_clock_freq; /* cpu_clock */
> +	u32 nr_cpus;
> +} __packed;
> +
> +struct system_loongson {
> +	u16 vers;     /* version of system_loongson */
> +	u32 ccnuma_smp; /* 0: no numa; 1: has numa */
> +	u32 sing_double_channel; /* 1:single; 2:double */
> +} __packed;
> +
> +struct irq_source_routing_table {
> +	u16 vers;
> +	u16 size;
> +	u16 rtr_bus;
> +	u16 rtr_devfn;
> +	u32 vendor;
> +	u32 device;
> +	u32 PIC_type;   /* conform use HT or PCI to route to CPU-PIC */
> +	u64 ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */
> +	u64 ht_enable;  /* irqs used in this PIC */
> +	u32 node_id;    /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */
> +	u64 pci_mem_start_addr;
> +	u64 pci_mem_end_addr;
> +	u64 pci_io_start_addr;
> +	u64 pci_io_end_addr;
> +	u64 pci_config_addr;
> +} __packed;
> +
> +struct interface_info {
> +	u16 vers; /* version of the specificition */
> +	u16 size;
> +	u8  flag;
> +	char description[64];
> +} __packed;
> +
> +#define MAX_RESOURCE_NUMBER 128
> +struct resource_loongson {
> +	u64 start; /* resource start address */
> +	u64 end;   /* resource end address */
> +	char name[64];
> +	u32 flags;
> +};
> +
> +struct archdev_data {};  /* arch specific additions */
> +
> +struct board_devices {
> +	char name[64];    /* hold the device name */
> +	u32 num_resources; /* number of device_resource */
> +	/* for each device's resource */
> +	struct resource_loongson resource[MAX_RESOURCE_NUMBER];
> +	/* arch specific additions */
> +	struct archdev_data archdata;
> +};
> +
> +struct loongson_special_attribute {
> +	u16 vers;     /* version of this special */
> +	char special_name[64]; /* special_atribute_name */
> +	u32 loongson_special_type; /* type of special device */
> +	/* for each device's resource */
> +	struct resource_loongson resource[MAX_RESOURCE_NUMBER];
> +};
> +
> +struct loongson_params {
> +	u64 memory_offset;	/* efi_memory_map_loongson struct offset */
> +	u64 cpu_offset;		/* efi_cpuinfo_loongson struct offset */
> +	u64 system_offset;	/* system_loongson struct offset */
> +	u64 irq_offset;		/* irq_source_routing_table struct offset */
> +	u64 interface_offset;	/* interface_info struct offset */
> +	u64 special_offset;	/* loongson_special_attribute struct offset */
> +	u64 boarddev_table_offset;  /* board_devices offset */
> +};
> +
> +struct smbios_tables {
> +	u16 vers;     /* version of smbios */
> +	u64 vga_bios; /* vga_bios address */
> +	struct loongson_params lp;
> +};
> +
> +struct efi_reset_system_t {
> +	u64 ResetCold;
> +	u64 ResetWarm;
> +	u64 ResetType;
> +	u64 Shutdown;
> +};
> +
> +struct efi_loongson {
> +	u64 mps;	/* MPS table */
> +	u64 acpi;	/* ACPI table (IA64 ext 0.71) */
> +	u64 acpi20;	/* ACPI table (ACPI 2.0) */
> +	struct smbios_tables smbios;	/* SM BIOS table */
> +	u64 sal_systab;	/* SAL system table */
> +	u64 boot_info;	/* boot info table */
> +};
> +
> +struct boot_params {
> +	struct efi_loongson efi;
> +	struct efi_reset_system_t reset_system;
> +};
> +
> +struct loongson_system_configuration {
> +	u32 nr_cpus;
> +	enum loongson_cpu_type cputype;
> +	u64 ht_control_base;
> +	u64 pci_mem_start_addr;
> +	u64 pci_mem_end_addr;
> +	u64 pci_io_base;
> +	u64 restart_addr;
> +	u64 poweroff_addr;
> +	u64 vgabios_addr;
> +};
> +
> +extern struct efi_memory_map_loongson *emap;
> +extern struct loongson_system_configuration loongson_sysconf;
> +#endif
> diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
> index b286534..5913ea0 100644
> --- a/arch/mips/include/asm/mach-loongson/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson/loongson.h
> @@ -24,8 +24,8 @@ extern void mach_prepare_reboot(void);
>   extern void mach_prepare_shutdown(void);
>
>   /* environment arguments from bootloader */
> -extern unsigned long cpu_clock_freq;
> -extern unsigned long memsize, highmemsize;
> +extern u32 cpu_clock_freq;
> +extern u32 memsize, highmemsize;
>
>   /* loongson-specific command line, env and memory initialization */
>   extern void __init prom_init_memory(void);
> diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
> index 0a18fcf..ba2b6df 100644
> --- a/arch/mips/loongson/common/env.c
> +++ b/arch/mips/loongson/common/env.c
> @@ -18,29 +18,37 @@
>    * option) any later version.
>    */
>   #include <linux/module.h>
> -
>   #include <asm/bootinfo.h>
> -
>   #include <loongson.h>
> +#include <boot_param.h>
> +
> +struct boot_params *boot_p;
> +struct loongson_params *loongson_p;
> +
> +struct efi_cpuinfo_loongson *ecpu;
> +struct efi_memory_map_loongson *emap;
> +struct system_loongson *esys;
> +struct irq_source_routing_table *eirq_source;
> +struct loongson_system_configuration loongson_sysconf;

Aside from emap and loongson_sysconf, there's no need for the rest of 
these to be globals, as far as I can see they aren't used outside 
prom_init_env(). Also, esys doesn't appear to be used at all.

Thanks,
Alex

>
> -unsigned long cpu_clock_freq;
> +u32 cpu_clock_freq;
>   EXPORT_SYMBOL(cpu_clock_freq);
> -unsigned long memsize, highmemsize;
>
>   #define parse_even_earlier(res, option, p)				\
>   do {									\
>   	unsigned int tmp __maybe_unused;				\
>   									\
>   	if (strncmp(option, (char *)p, strlen(option)) == 0)		\
> -		tmp = strict_strtol((char *)p + strlen(option"="), 10, &res); \
> +		tmp = kstrtou32((char *)p + strlen(option"="), 10, &res); \
>   } while (0)
>
>   void __init prom_init_env(void)
>   {
>   	/* pmon passes arguments in 32bit pointers */
> -	int *_prom_envp;
> -	unsigned long bus_clock;
>   	unsigned int processor_id;
> +
> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
> +	int *_prom_envp;
>   	long l;
>
>   	/* firmware arguments are initialized in head.S */
> @@ -48,7 +56,6 @@ void __init prom_init_env(void)
>
>   	l = (long)*_prom_envp;
>   	while (l != 0) {
> -		parse_even_earlier(bus_clock, "busclock", l);
>   		parse_even_earlier(cpu_clock_freq, "cpuclock", l);
>   		parse_even_earlier(memsize, "memsize", l);
>   		parse_even_earlier(highmemsize, "highmemsize", l);
> @@ -57,8 +64,38 @@ void __init prom_init_env(void)
>   	}
>   	if (memsize == 0)
>   		memsize = 256;
> -	if (bus_clock == 0)
> -		bus_clock = 66000000;
> +	pr_info("memsize=%ld, highmemsize=%ld\n", memsize, highmemsize);
> +#else
> +	/* firmware arguments are initialized in head.S */
> +	boot_p = (struct boot_params *)fw_arg2;
> +	loongson_p = &(boot_p->efi.smbios.lp);
> +
> +	ecpu = (struct efi_cpuinfo_loongson *)
> +		((u64)loongson_p + loongson_p->cpu_offset);
> +	emap = (struct efi_memory_map_loongson *)
> +		((u64)loongson_p + loongson_p->memory_offset);
> +	eirq_source = (struct irq_source_routing_table *)
> +		((u64)loongson_p + loongson_p->irq_offset);
> +
> +	cpu_clock_freq = ecpu->cpu_clock_freq;
> +	loongson_sysconf.cputype = ecpu->cputype;
> +	loongson_sysconf.nr_cpus = ecpu->nr_cpus;
> +	if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
> +		loongson_sysconf.nr_cpus = NR_CPUS;
> +
> +	loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr;
> +	loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
> +	loongson_sysconf.pci_io_base = eirq_source->pci_io_start_addr;
> +
> +	loongson_sysconf.restart_addr = boot_p->reset_system.ResetWarm;
> +	loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
> +
> +	loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
> +	loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios;
> +	pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
> +		loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
> +		loongson_sysconf.vgabios_addr);
> +#endif
>   	if (cpu_clock_freq == 0) {
>   		processor_id = (&current_cpu_data)->processor_id;
>   		switch (processor_id & PRID_REV_MASK) {
> @@ -68,12 +105,13 @@ void __init prom_init_env(void)
>   		case PRID_REV_LOONGSON2F:
>   			cpu_clock_freq = 797000000;
>   			break;
> +		case PRID_REV_LOONGSON3A:
> +			cpu_clock_freq = 900000000;
> +			break;
>   		default:
>   			cpu_clock_freq = 100000000;
>   			break;
>   		}
>   	}
> -
> -	pr_info("busclock=%ld, cpuclock=%ld, memsize=%ld, highmemsize=%ld\n",
> -		bus_clock, cpu_clock_freq, memsize, highmemsize);
> +	pr_info("CpuClock = %u\n", cpu_clock_freq);
>   }
> diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
> index ae7af1f..81ba3b4 100644
> --- a/arch/mips/loongson/common/init.c
> +++ b/arch/mips/loongson/common/init.c
> @@ -17,10 +17,6 @@ unsigned long __maybe_unused _loongson_addrwincfg_base;
>
>   void __init prom_init(void)
>   {
> -	/* init base address of io space */
> -	set_io_port_base((unsigned long)
> -		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
> -
>   #ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
>   	_loongson_addrwincfg_base = (unsigned long)
>   		ioremap(LOONGSON_ADDRWINCFG_BASE, LOONGSON_ADDRWINCFG_SIZE);
> @@ -28,6 +24,11 @@ void __init prom_init(void)
>
>   	prom_init_cmdline();
>   	prom_init_env();
> +
> +	/* init base address of io space */
> +	set_io_port_base((unsigned long)
> +		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
> +
>   	prom_init_memory();
>
>   	/*init the uart base address */
> diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c
> index 8626a42..42b2431 100644
> --- a/arch/mips/loongson/common/mem.c
> +++ b/arch/mips/loongson/common/mem.c
> @@ -11,9 +11,14 @@
>   #include <asm/bootinfo.h>
>
>   #include <loongson.h>
> +#include <boot_param.h>
>   #include <mem.h>
>   #include <pci.h>
>
> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
> +
> +u32 memsize, highmemsize;
> +
>   void __init prom_init_memory(void)
>   {
>   	add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
> @@ -49,6 +54,43 @@ void __init prom_init_memory(void)
>   #endif /* !CONFIG_64BIT */
>   }
>
> +#else /* CONFIG_LEFI_FIRMWARE_INTERFACE */
> +
> +void __init prom_init_memory(void)
> +{
> +	int i;
> +	u32 node_id;
> +	u32 mem_type;
> +
> +	/* parse memory information */
> +	for (i = 0; i < emap->nr_map; i++) {
> +		node_id = emap->map[i].node_id;
> +		mem_type = emap->map[i].mem_type;
> +
> +		if (node_id == 0) {
> +			switch (mem_type) {
> +			case SYSTEM_RAM_LOW:
> +				add_memory_region(emap->map[i].mem_start,
> +					(u64)emap->map[i].mem_size << 20,
> +					BOOT_MEM_RAM);
> +				break;
> +			case SYSTEM_RAM_HIGH:
> +				add_memory_region(emap->map[i].mem_start,
> +					(u64)emap->map[i].mem_size << 20,
> +					BOOT_MEM_RAM);
> +				break;
> +			case MEM_RESERVED:
> +				add_memory_region(emap->map[i].mem_start,
> +					(u64)emap->map[i].mem_size << 20,
> +					BOOT_MEM_RESERVED);
> +				break;
> +			}
> +		}
> +	}
> +}
> +
> +#endif /* CONFIG_LEFI_FIRMWARE_INTERFACE */
> +
>   /* override of arch/mips/mm/cache.c: __uncached_access */
>   int __uncached_access(struct file *file, unsigned long addr)
>   {
> diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson/common/pci.c
> index fa77844..003ab4e 100644
> --- a/arch/mips/loongson/common/pci.c
> +++ b/arch/mips/loongson/common/pci.c
> @@ -11,6 +11,7 @@
>
>   #include <pci.h>
>   #include <loongson.h>
> +#include <boot_param.h>
>
>   static struct resource loongson_pci_mem_resource = {
>   	.name	= "pci memory space",
> @@ -82,7 +83,10 @@ static int __init pcibios_init(void)
>   	setup_pcimap();
>
>   	loongson_pci_controller.io_map_base = mips_io_port_base;
> -
> +#ifdef CONFIG_LEFI_FIRMWARE_INTERFACE
> +	loongson_pci_mem_resource.start = loongson_sysconf.pci_mem_start_addr;
> +	loongson_pci_mem_resource.end = loongson_sysconf.pci_mem_end_addr;
> +#endif
>   	register_pci_controller(&loongson_pci_controller);
>
>   	return 0;
> diff --git a/arch/mips/loongson/common/reset.c b/arch/mips/loongson/common/reset.c
> index 65bfbb5..a60715e 100644
> --- a/arch/mips/loongson/common/reset.c
> +++ b/arch/mips/loongson/common/reset.c
> @@ -16,6 +16,7 @@
>   #include <asm/reboot.h>
>
>   #include <loongson.h>
> +#include <boot_param.h>
>
>   static inline void loongson_reboot(void)
>   {
> @@ -37,17 +38,37 @@ static inline void loongson_reboot(void)
>
>   static void loongson_restart(char *command)
>   {
> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
>   	/* do preparation for reboot */
>   	mach_prepare_reboot();
>
>   	/* reboot via jumping to boot base address */
>   	loongson_reboot();
> +#else
> +	void (*fw_restart)(void) = (void *)loongson_sysconf.restart_addr;
> +
> +	fw_restart();
> +	while (1) {
> +		if (cpu_wait)
> +			cpu_wait();
> +	}
> +#endif
>   }
>
>   static void loongson_poweroff(void)
>   {
> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
>   	mach_prepare_shutdown();
>   	unreachable();
> +#else
> +	void (*fw_poweroff)(void) = (void *)loongson_sysconf.poweroff_addr;
> +
> +	fw_poweroff();
> +	while (1) {
> +		if (cpu_wait)
> +			cpu_wait();
> +	}
> +#endif
>   }
>
>   static void loongson_halt(void)
>

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

* Re: [PATCH V16 04/12] MIPS: Loongson: Add UEFI-like firmware interface (LEFI) support
@ 2014-01-09 12:37     ` Alex Smith
  0 siblings, 0 replies; 55+ messages in thread
From: Alex Smith @ 2014-01-09 12:37 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, Aurelien Jarno,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

Hi,

On 08/01/14 02:44, Huacai Chen wrote:
> The new UEFI-like firmware interface (LEFI, i.e. Loongson Unified
> Firmware Interface) has 3 advantages:
>
> 1, Firmware export a physical memory map which is similar to X86's
>     E820 map, so prom_init_memory() will be more elegant that #ifdef
>     clauses can be removed.
> 2, Firmware export a pci irq routing table, we no longer need pci
>     irq routing fixup in kernel's code.
> 3, Firmware has a built-in vga bios, and its address is exported,
>     the linux kernel no longer need an embedded blob.
>
> With the LEFI interface, Loongson-3A/2G and all their successors can use
> a unified kernel. All Loongson-based machines support this new interface
> except 2E/2F series.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>   arch/mips/include/asm/mach-loongson/boot_param.h |  159 ++++++++++++++++++++++
>   arch/mips/include/asm/mach-loongson/loongson.h   |    4 +-
>   arch/mips/loongson/common/env.c                  |   64 +++++++--
>   arch/mips/loongson/common/init.c                 |    9 +-
>   arch/mips/loongson/common/mem.c                  |   42 ++++++
>   arch/mips/loongson/common/pci.c                  |    6 +-
>   arch/mips/loongson/common/reset.c                |   21 +++
>   7 files changed, 285 insertions(+), 20 deletions(-)
>   create mode 100644 arch/mips/include/asm/mach-loongson/boot_param.h
>
> diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h
> new file mode 100644
> index 0000000..234c0eb
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson/boot_param.h
> @@ -0,0 +1,159 @@
> +#ifndef __ASM_MACH_LOONGSON_BOOT_PARAM_H_
> +#define __ASM_MACH_LOONGSON_BOOT_PARAM_H_
> +
> +#define SYSTEM_RAM_LOW		1
> +#define SYSTEM_RAM_HIGH		2
> +#define MEM_RESERVED		3
> +#define PCI_IO			4
> +#define PCI_MEM			5
> +#define LOONGSON_CFG_REG	6
> +#define VIDEO_ROM		7
> +#define ADAPTER_ROM		8
> +#define ACPI_TABLE		9
> +#define MAX_MEMORY_TYPE		10
> +
> +#define LOONGSON3_BOOT_MEM_MAP_MAX 128
> +struct efi_memory_map_loongson {
> +	u16 vers;	/* version of efi_memory_map */
> +	u32 nr_map;	/* number of memory_maps */
> +	u32 mem_freq;	/* memory frequence */
> +	struct mem_map {
> +		u32 node_id;	/* node_id which memory attached to */
> +		u32 mem_type;	/* system memory, pci memory, pci io, etc. */
> +		u64 mem_start;	/* memory map start address */
> +		u32 mem_size;	/* each memory_map size, not the total size */
> +	} map[LOONGSON3_BOOT_MEM_MAP_MAX];
> +} __packed;
> +
> +enum loongson_cpu_type {
> +	Loongson_2E = 0,
> +	Loongson_2F = 1,
> +	Loongson_3A = 2,
> +	Loongson_3B = 3,
> +	Loongson_1A = 4,
> +	Loongson_1B = 5
> +};
> +
> +/*
> + * Capability and feature descriptor structure for MIPS CPU
> + */
> +struct efi_cpuinfo_loongson {
> +	u16 vers;     /* version of efi_cpuinfo_loongson */
> +	u32 processor_id; /* PRID, e.g. 6305, 6306 */
> +	u32 cputype;  /* Loongson_3A/3B, etc. */
> +	u32 total_node;   /* num of total numa nodes */
> +	u32 cpu_startup_core_id; /* Core id */
> +	u32 cpu_clock_freq; /* cpu_clock */
> +	u32 nr_cpus;
> +} __packed;
> +
> +struct system_loongson {
> +	u16 vers;     /* version of system_loongson */
> +	u32 ccnuma_smp; /* 0: no numa; 1: has numa */
> +	u32 sing_double_channel; /* 1:single; 2:double */
> +} __packed;
> +
> +struct irq_source_routing_table {
> +	u16 vers;
> +	u16 size;
> +	u16 rtr_bus;
> +	u16 rtr_devfn;
> +	u32 vendor;
> +	u32 device;
> +	u32 PIC_type;   /* conform use HT or PCI to route to CPU-PIC */
> +	u64 ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */
> +	u64 ht_enable;  /* irqs used in this PIC */
> +	u32 node_id;    /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */
> +	u64 pci_mem_start_addr;
> +	u64 pci_mem_end_addr;
> +	u64 pci_io_start_addr;
> +	u64 pci_io_end_addr;
> +	u64 pci_config_addr;
> +} __packed;
> +
> +struct interface_info {
> +	u16 vers; /* version of the specificition */
> +	u16 size;
> +	u8  flag;
> +	char description[64];
> +} __packed;
> +
> +#define MAX_RESOURCE_NUMBER 128
> +struct resource_loongson {
> +	u64 start; /* resource start address */
> +	u64 end;   /* resource end address */
> +	char name[64];
> +	u32 flags;
> +};
> +
> +struct archdev_data {};  /* arch specific additions */
> +
> +struct board_devices {
> +	char name[64];    /* hold the device name */
> +	u32 num_resources; /* number of device_resource */
> +	/* for each device's resource */
> +	struct resource_loongson resource[MAX_RESOURCE_NUMBER];
> +	/* arch specific additions */
> +	struct archdev_data archdata;
> +};
> +
> +struct loongson_special_attribute {
> +	u16 vers;     /* version of this special */
> +	char special_name[64]; /* special_atribute_name */
> +	u32 loongson_special_type; /* type of special device */
> +	/* for each device's resource */
> +	struct resource_loongson resource[MAX_RESOURCE_NUMBER];
> +};
> +
> +struct loongson_params {
> +	u64 memory_offset;	/* efi_memory_map_loongson struct offset */
> +	u64 cpu_offset;		/* efi_cpuinfo_loongson struct offset */
> +	u64 system_offset;	/* system_loongson struct offset */
> +	u64 irq_offset;		/* irq_source_routing_table struct offset */
> +	u64 interface_offset;	/* interface_info struct offset */
> +	u64 special_offset;	/* loongson_special_attribute struct offset */
> +	u64 boarddev_table_offset;  /* board_devices offset */
> +};
> +
> +struct smbios_tables {
> +	u16 vers;     /* version of smbios */
> +	u64 vga_bios; /* vga_bios address */
> +	struct loongson_params lp;
> +};
> +
> +struct efi_reset_system_t {
> +	u64 ResetCold;
> +	u64 ResetWarm;
> +	u64 ResetType;
> +	u64 Shutdown;
> +};
> +
> +struct efi_loongson {
> +	u64 mps;	/* MPS table */
> +	u64 acpi;	/* ACPI table (IA64 ext 0.71) */
> +	u64 acpi20;	/* ACPI table (ACPI 2.0) */
> +	struct smbios_tables smbios;	/* SM BIOS table */
> +	u64 sal_systab;	/* SAL system table */
> +	u64 boot_info;	/* boot info table */
> +};
> +
> +struct boot_params {
> +	struct efi_loongson efi;
> +	struct efi_reset_system_t reset_system;
> +};
> +
> +struct loongson_system_configuration {
> +	u32 nr_cpus;
> +	enum loongson_cpu_type cputype;
> +	u64 ht_control_base;
> +	u64 pci_mem_start_addr;
> +	u64 pci_mem_end_addr;
> +	u64 pci_io_base;
> +	u64 restart_addr;
> +	u64 poweroff_addr;
> +	u64 vgabios_addr;
> +};
> +
> +extern struct efi_memory_map_loongson *emap;
> +extern struct loongson_system_configuration loongson_sysconf;
> +#endif
> diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
> index b286534..5913ea0 100644
> --- a/arch/mips/include/asm/mach-loongson/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson/loongson.h
> @@ -24,8 +24,8 @@ extern void mach_prepare_reboot(void);
>   extern void mach_prepare_shutdown(void);
>
>   /* environment arguments from bootloader */
> -extern unsigned long cpu_clock_freq;
> -extern unsigned long memsize, highmemsize;
> +extern u32 cpu_clock_freq;
> +extern u32 memsize, highmemsize;
>
>   /* loongson-specific command line, env and memory initialization */
>   extern void __init prom_init_memory(void);
> diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
> index 0a18fcf..ba2b6df 100644
> --- a/arch/mips/loongson/common/env.c
> +++ b/arch/mips/loongson/common/env.c
> @@ -18,29 +18,37 @@
>    * option) any later version.
>    */
>   #include <linux/module.h>
> -
>   #include <asm/bootinfo.h>
> -
>   #include <loongson.h>
> +#include <boot_param.h>
> +
> +struct boot_params *boot_p;
> +struct loongson_params *loongson_p;
> +
> +struct efi_cpuinfo_loongson *ecpu;
> +struct efi_memory_map_loongson *emap;
> +struct system_loongson *esys;
> +struct irq_source_routing_table *eirq_source;
> +struct loongson_system_configuration loongson_sysconf;

Aside from emap and loongson_sysconf, there's no need for the rest of 
these to be globals, as far as I can see they aren't used outside 
prom_init_env(). Also, esys doesn't appear to be used at all.

Thanks,
Alex

>
> -unsigned long cpu_clock_freq;
> +u32 cpu_clock_freq;
>   EXPORT_SYMBOL(cpu_clock_freq);
> -unsigned long memsize, highmemsize;
>
>   #define parse_even_earlier(res, option, p)				\
>   do {									\
>   	unsigned int tmp __maybe_unused;				\
>   									\
>   	if (strncmp(option, (char *)p, strlen(option)) == 0)		\
> -		tmp = strict_strtol((char *)p + strlen(option"="), 10, &res); \
> +		tmp = kstrtou32((char *)p + strlen(option"="), 10, &res); \
>   } while (0)
>
>   void __init prom_init_env(void)
>   {
>   	/* pmon passes arguments in 32bit pointers */
> -	int *_prom_envp;
> -	unsigned long bus_clock;
>   	unsigned int processor_id;
> +
> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
> +	int *_prom_envp;
>   	long l;
>
>   	/* firmware arguments are initialized in head.S */
> @@ -48,7 +56,6 @@ void __init prom_init_env(void)
>
>   	l = (long)*_prom_envp;
>   	while (l != 0) {
> -		parse_even_earlier(bus_clock, "busclock", l);
>   		parse_even_earlier(cpu_clock_freq, "cpuclock", l);
>   		parse_even_earlier(memsize, "memsize", l);
>   		parse_even_earlier(highmemsize, "highmemsize", l);
> @@ -57,8 +64,38 @@ void __init prom_init_env(void)
>   	}
>   	if (memsize == 0)
>   		memsize = 256;
> -	if (bus_clock == 0)
> -		bus_clock = 66000000;
> +	pr_info("memsize=%ld, highmemsize=%ld\n", memsize, highmemsize);
> +#else
> +	/* firmware arguments are initialized in head.S */
> +	boot_p = (struct boot_params *)fw_arg2;
> +	loongson_p = &(boot_p->efi.smbios.lp);
> +
> +	ecpu = (struct efi_cpuinfo_loongson *)
> +		((u64)loongson_p + loongson_p->cpu_offset);
> +	emap = (struct efi_memory_map_loongson *)
> +		((u64)loongson_p + loongson_p->memory_offset);
> +	eirq_source = (struct irq_source_routing_table *)
> +		((u64)loongson_p + loongson_p->irq_offset);
> +
> +	cpu_clock_freq = ecpu->cpu_clock_freq;
> +	loongson_sysconf.cputype = ecpu->cputype;
> +	loongson_sysconf.nr_cpus = ecpu->nr_cpus;
> +	if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
> +		loongson_sysconf.nr_cpus = NR_CPUS;
> +
> +	loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr;
> +	loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
> +	loongson_sysconf.pci_io_base = eirq_source->pci_io_start_addr;
> +
> +	loongson_sysconf.restart_addr = boot_p->reset_system.ResetWarm;
> +	loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
> +
> +	loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
> +	loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios;
> +	pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
> +		loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
> +		loongson_sysconf.vgabios_addr);
> +#endif
>   	if (cpu_clock_freq == 0) {
>   		processor_id = (&current_cpu_data)->processor_id;
>   		switch (processor_id & PRID_REV_MASK) {
> @@ -68,12 +105,13 @@ void __init prom_init_env(void)
>   		case PRID_REV_LOONGSON2F:
>   			cpu_clock_freq = 797000000;
>   			break;
> +		case PRID_REV_LOONGSON3A:
> +			cpu_clock_freq = 900000000;
> +			break;
>   		default:
>   			cpu_clock_freq = 100000000;
>   			break;
>   		}
>   	}
> -
> -	pr_info("busclock=%ld, cpuclock=%ld, memsize=%ld, highmemsize=%ld\n",
> -		bus_clock, cpu_clock_freq, memsize, highmemsize);
> +	pr_info("CpuClock = %u\n", cpu_clock_freq);
>   }
> diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
> index ae7af1f..81ba3b4 100644
> --- a/arch/mips/loongson/common/init.c
> +++ b/arch/mips/loongson/common/init.c
> @@ -17,10 +17,6 @@ unsigned long __maybe_unused _loongson_addrwincfg_base;
>
>   void __init prom_init(void)
>   {
> -	/* init base address of io space */
> -	set_io_port_base((unsigned long)
> -		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
> -
>   #ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
>   	_loongson_addrwincfg_base = (unsigned long)
>   		ioremap(LOONGSON_ADDRWINCFG_BASE, LOONGSON_ADDRWINCFG_SIZE);
> @@ -28,6 +24,11 @@ void __init prom_init(void)
>
>   	prom_init_cmdline();
>   	prom_init_env();
> +
> +	/* init base address of io space */
> +	set_io_port_base((unsigned long)
> +		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
> +
>   	prom_init_memory();
>
>   	/*init the uart base address */
> diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c
> index 8626a42..42b2431 100644
> --- a/arch/mips/loongson/common/mem.c
> +++ b/arch/mips/loongson/common/mem.c
> @@ -11,9 +11,14 @@
>   #include <asm/bootinfo.h>
>
>   #include <loongson.h>
> +#include <boot_param.h>
>   #include <mem.h>
>   #include <pci.h>
>
> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
> +
> +u32 memsize, highmemsize;
> +
>   void __init prom_init_memory(void)
>   {
>   	add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
> @@ -49,6 +54,43 @@ void __init prom_init_memory(void)
>   #endif /* !CONFIG_64BIT */
>   }
>
> +#else /* CONFIG_LEFI_FIRMWARE_INTERFACE */
> +
> +void __init prom_init_memory(void)
> +{
> +	int i;
> +	u32 node_id;
> +	u32 mem_type;
> +
> +	/* parse memory information */
> +	for (i = 0; i < emap->nr_map; i++) {
> +		node_id = emap->map[i].node_id;
> +		mem_type = emap->map[i].mem_type;
> +
> +		if (node_id == 0) {
> +			switch (mem_type) {
> +			case SYSTEM_RAM_LOW:
> +				add_memory_region(emap->map[i].mem_start,
> +					(u64)emap->map[i].mem_size << 20,
> +					BOOT_MEM_RAM);
> +				break;
> +			case SYSTEM_RAM_HIGH:
> +				add_memory_region(emap->map[i].mem_start,
> +					(u64)emap->map[i].mem_size << 20,
> +					BOOT_MEM_RAM);
> +				break;
> +			case MEM_RESERVED:
> +				add_memory_region(emap->map[i].mem_start,
> +					(u64)emap->map[i].mem_size << 20,
> +					BOOT_MEM_RESERVED);
> +				break;
> +			}
> +		}
> +	}
> +}
> +
> +#endif /* CONFIG_LEFI_FIRMWARE_INTERFACE */
> +
>   /* override of arch/mips/mm/cache.c: __uncached_access */
>   int __uncached_access(struct file *file, unsigned long addr)
>   {
> diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson/common/pci.c
> index fa77844..003ab4e 100644
> --- a/arch/mips/loongson/common/pci.c
> +++ b/arch/mips/loongson/common/pci.c
> @@ -11,6 +11,7 @@
>
>   #include <pci.h>
>   #include <loongson.h>
> +#include <boot_param.h>
>
>   static struct resource loongson_pci_mem_resource = {
>   	.name	= "pci memory space",
> @@ -82,7 +83,10 @@ static int __init pcibios_init(void)
>   	setup_pcimap();
>
>   	loongson_pci_controller.io_map_base = mips_io_port_base;
> -
> +#ifdef CONFIG_LEFI_FIRMWARE_INTERFACE
> +	loongson_pci_mem_resource.start = loongson_sysconf.pci_mem_start_addr;
> +	loongson_pci_mem_resource.end = loongson_sysconf.pci_mem_end_addr;
> +#endif
>   	register_pci_controller(&loongson_pci_controller);
>
>   	return 0;
> diff --git a/arch/mips/loongson/common/reset.c b/arch/mips/loongson/common/reset.c
> index 65bfbb5..a60715e 100644
> --- a/arch/mips/loongson/common/reset.c
> +++ b/arch/mips/loongson/common/reset.c
> @@ -16,6 +16,7 @@
>   #include <asm/reboot.h>
>
>   #include <loongson.h>
> +#include <boot_param.h>
>
>   static inline void loongson_reboot(void)
>   {
> @@ -37,17 +38,37 @@ static inline void loongson_reboot(void)
>
>   static void loongson_restart(char *command)
>   {
> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
>   	/* do preparation for reboot */
>   	mach_prepare_reboot();
>
>   	/* reboot via jumping to boot base address */
>   	loongson_reboot();
> +#else
> +	void (*fw_restart)(void) = (void *)loongson_sysconf.restart_addr;
> +
> +	fw_restart();
> +	while (1) {
> +		if (cpu_wait)
> +			cpu_wait();
> +	}
> +#endif
>   }
>
>   static void loongson_poweroff(void)
>   {
> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
>   	mach_prepare_shutdown();
>   	unreachable();
> +#else
> +	void (*fw_poweroff)(void) = (void *)loongson_sysconf.poweroff_addr;
> +
> +	fw_poweroff();
> +	while (1) {
> +		if (cpu_wait)
> +			cpu_wait();
> +	}
> +#endif
>   }
>
>   static void loongson_halt(void)
>

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

* Re: [PATCH V16 04/12] MIPS: Loongson: Add UEFI-like firmware interface (LEFI) support
@ 2014-01-09 12:43       ` Alex Smith
  0 siblings, 0 replies; 55+ messages in thread
From: Alex Smith @ 2014-01-09 12:43 UTC (permalink / raw)
  To: Aurelien Jarno, Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On 08/01/14 22:58, Aurelien Jarno wrote:
> On Wed, Jan 08, 2014 at 10:44:20AM +0800, Huacai Chen wrote:
>> The new UEFI-like firmware interface (LEFI, i.e. Loongson Unified
>> Firmware Interface) has 3 advantages:
>>
>> 1, Firmware export a physical memory map which is similar to X86's
>>     E820 map, so prom_init_memory() will be more elegant that #ifdef
>>     clauses can be removed.
>> 2, Firmware export a pci irq routing table, we no longer need pci
>>     irq routing fixup in kernel's code.
>> 3, Firmware has a built-in vga bios, and its address is exported,
>>     the linux kernel no longer need an embedded blob.
>>
>> With the LEFI interface, Loongson-3A/2G and all their successors can use
>> a unified kernel. All Loongson-based machines support this new interface
>> except 2E/2F series.
>>
>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
>> Signed-off-by: Hongliang Tao <taohl@lemote.com>
>> Signed-off-by: Hua Yan <yanh@lemote.com>
>> ---
>>   arch/mips/include/asm/mach-loongson/boot_param.h |  159 ++++++++++++++++++++++
>>   arch/mips/include/asm/mach-loongson/loongson.h   |    4 +-
>>   arch/mips/loongson/common/env.c                  |   64 +++++++--
>>   arch/mips/loongson/common/init.c                 |    9 +-
>>   arch/mips/loongson/common/mem.c                  |   42 ++++++
>>   arch/mips/loongson/common/pci.c                  |    6 +-
>>   arch/mips/loongson/common/reset.c                |   21 +++
>>   7 files changed, 285 insertions(+), 20 deletions(-)
>>   create mode 100644 arch/mips/include/asm/mach-loongson/boot_param.h
>>
>> diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h
>> new file mode 100644
>> index 0000000..234c0eb
>> --- /dev/null
>> +++ b/arch/mips/include/asm/mach-loongson/boot_param.h
>> @@ -0,0 +1,159 @@
>> +#ifndef __ASM_MACH_LOONGSON_BOOT_PARAM_H_
>> +#define __ASM_MACH_LOONGSON_BOOT_PARAM_H_
>> +
>> +#define SYSTEM_RAM_LOW		1
>> +#define SYSTEM_RAM_HIGH		2
>> +#define MEM_RESERVED		3
>> +#define PCI_IO			4
>> +#define PCI_MEM			5
>> +#define LOONGSON_CFG_REG	6
>> +#define VIDEO_ROM		7
>> +#define ADAPTER_ROM		8
>> +#define ACPI_TABLE		9
>> +#define MAX_MEMORY_TYPE		10
>> +
>> +#define LOONGSON3_BOOT_MEM_MAP_MAX 128
>> +struct efi_memory_map_loongson {
>> +	u16 vers;	/* version of efi_memory_map */
>> +	u32 nr_map;	/* number of memory_maps */
>> +	u32 mem_freq;	/* memory frequence */
>> +	struct mem_map {
>> +		u32 node_id;	/* node_id which memory attached to */
>> +		u32 mem_type;	/* system memory, pci memory, pci io, etc. */
>> +		u64 mem_start;	/* memory map start address */
>> +		u32 mem_size;	/* each memory_map size, not the total size */
>> +	} map[LOONGSON3_BOOT_MEM_MAP_MAX];
>> +} __packed;
>> +
>> +enum loongson_cpu_type {
>> +	Loongson_2E = 0,
>> +	Loongson_2F = 1,
>> +	Loongson_3A = 2,
>> +	Loongson_3B = 3,
>> +	Loongson_1A = 4,
>> +	Loongson_1B = 5
>> +};
>> +
>> +/*
>> + * Capability and feature descriptor structure for MIPS CPU
>> + */
>> +struct efi_cpuinfo_loongson {
>> +	u16 vers;     /* version of efi_cpuinfo_loongson */
>> +	u32 processor_id; /* PRID, e.g. 6305, 6306 */
>> +	u32 cputype;  /* Loongson_3A/3B, etc. */
>> +	u32 total_node;   /* num of total numa nodes */
>> +	u32 cpu_startup_core_id; /* Core id */
>> +	u32 cpu_clock_freq; /* cpu_clock */
>> +	u32 nr_cpus;
>> +} __packed;
>> +
>> +struct system_loongson {
>> +	u16 vers;     /* version of system_loongson */
>> +	u32 ccnuma_smp; /* 0: no numa; 1: has numa */
>> +	u32 sing_double_channel; /* 1:single; 2:double */
>> +} __packed;
>> +
>> +struct irq_source_routing_table {
>> +	u16 vers;
>> +	u16 size;
>> +	u16 rtr_bus;
>> +	u16 rtr_devfn;
>> +	u32 vendor;
>> +	u32 device;
>> +	u32 PIC_type;   /* conform use HT or PCI to route to CPU-PIC */
>> +	u64 ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */
>> +	u64 ht_enable;  /* irqs used in this PIC */
>> +	u32 node_id;    /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */
>> +	u64 pci_mem_start_addr;
>> +	u64 pci_mem_end_addr;
>> +	u64 pci_io_start_addr;
>> +	u64 pci_io_end_addr;
>> +	u64 pci_config_addr;
>> +} __packed;
>> +
>> +struct interface_info {
>> +	u16 vers; /* version of the specificition */
>> +	u16 size;
>> +	u8  flag;
>> +	char description[64];
>> +} __packed;
>> +
>> +#define MAX_RESOURCE_NUMBER 128
>> +struct resource_loongson {
>> +	u64 start; /* resource start address */
>> +	u64 end;   /* resource end address */
>> +	char name[64];
>> +	u32 flags;
>> +};
>> +
>> +struct archdev_data {};  /* arch specific additions */
>> +
>> +struct board_devices {
>> +	char name[64];    /* hold the device name */
>> +	u32 num_resources; /* number of device_resource */
>> +	/* for each device's resource */
>> +	struct resource_loongson resource[MAX_RESOURCE_NUMBER];
>> +	/* arch specific additions */
>> +	struct archdev_data archdata;
>> +};
>> +
>> +struct loongson_special_attribute {
>> +	u16 vers;     /* version of this special */
>> +	char special_name[64]; /* special_atribute_name */
>> +	u32 loongson_special_type; /* type of special device */
>> +	/* for each device's resource */
>> +	struct resource_loongson resource[MAX_RESOURCE_NUMBER];
>> +};
>> +
>> +struct loongson_params {
>> +	u64 memory_offset;	/* efi_memory_map_loongson struct offset */
>> +	u64 cpu_offset;		/* efi_cpuinfo_loongson struct offset */
>> +	u64 system_offset;	/* system_loongson struct offset */
>> +	u64 irq_offset;		/* irq_source_routing_table struct offset */
>> +	u64 interface_offset;	/* interface_info struct offset */
>> +	u64 special_offset;	/* loongson_special_attribute struct offset */
>> +	u64 boarddev_table_offset;  /* board_devices offset */
>> +};
>> +
>> +struct smbios_tables {
>> +	u16 vers;     /* version of smbios */
>> +	u64 vga_bios; /* vga_bios address */
>> +	struct loongson_params lp;
>> +};
>> +
>> +struct efi_reset_system_t {
>> +	u64 ResetCold;
>> +	u64 ResetWarm;
>> +	u64 ResetType;
>> +	u64 Shutdown;
>> +};
>> +
>> +struct efi_loongson {
>> +	u64 mps;	/* MPS table */
>> +	u64 acpi;	/* ACPI table (IA64 ext 0.71) */
>> +	u64 acpi20;	/* ACPI table (ACPI 2.0) */
>> +	struct smbios_tables smbios;	/* SM BIOS table */
>> +	u64 sal_systab;	/* SAL system table */
>> +	u64 boot_info;	/* boot info table */
>> +};
>> +
>> +struct boot_params {
>> +	struct efi_loongson efi;
>> +	struct efi_reset_system_t reset_system;
>> +};
>> +
>> +struct loongson_system_configuration {
>> +	u32 nr_cpus;
>> +	enum loongson_cpu_type cputype;
>> +	u64 ht_control_base;
>> +	u64 pci_mem_start_addr;
>> +	u64 pci_mem_end_addr;
>> +	u64 pci_io_base;
>> +	u64 restart_addr;
>> +	u64 poweroff_addr;
>> +	u64 vgabios_addr;
>> +};
>> +
>> +extern struct efi_memory_map_loongson *emap;
>> +extern struct loongson_system_configuration loongson_sysconf;
>
> Thanks a lot for the loongson_sysconf struct, it looks a lot more clean
> now. What about emap? Isn't there any risk that the kernel reuse the
> corresponding memory and that its content is lost? It should be possible
> to hold a copy of this struct in loongson_sysconf.

I would guess that it won't be overwritten while it's still needed, 
since it is used to add memory regions in mem.c and then not used after 
that.

I wonder if it may be nicer to also add the emap pointer to 
loongson_sysconf to avoid having an extra global, or if not, at least 
rename it to a more descriptive name, such as loongson_memmap.

Alex

>
>
>> +#endif
>> diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
>> index b286534..5913ea0 100644
>> --- a/arch/mips/include/asm/mach-loongson/loongson.h
>> +++ b/arch/mips/include/asm/mach-loongson/loongson.h
>> @@ -24,8 +24,8 @@ extern void mach_prepare_reboot(void);
>>   extern void mach_prepare_shutdown(void);
>>
>>   /* environment arguments from bootloader */
>> -extern unsigned long cpu_clock_freq;
>> -extern unsigned long memsize, highmemsize;
>> +extern u32 cpu_clock_freq;
>> +extern u32 memsize, highmemsize;
>>
>>   /* loongson-specific command line, env and memory initialization */
>>   extern void __init prom_init_memory(void);
>> diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
>> index 0a18fcf..ba2b6df 100644
>> --- a/arch/mips/loongson/common/env.c
>> +++ b/arch/mips/loongson/common/env.c
>> @@ -18,29 +18,37 @@
>>    * option) any later version.
>>    */
>>   #include <linux/module.h>
>> -
>>   #include <asm/bootinfo.h>
>> -
>>   #include <loongson.h>
>> +#include <boot_param.h>
>> +
>> +struct boot_params *boot_p;
>> +struct loongson_params *loongson_p;
>> +
>> +struct efi_cpuinfo_loongson *ecpu;
>> +struct efi_memory_map_loongson *emap;
>> +struct system_loongson *esys;
>> +struct irq_source_routing_table *eirq_source;
>> +struct loongson_system_configuration loongson_sysconf;
>>
>> -unsigned long cpu_clock_freq;
>> +u32 cpu_clock_freq;
>>   EXPORT_SYMBOL(cpu_clock_freq);
>> -unsigned long memsize, highmemsize;
>>
>>   #define parse_even_earlier(res, option, p)				\
>>   do {									\
>>   	unsigned int tmp __maybe_unused;				\
>>   									\
>>   	if (strncmp(option, (char *)p, strlen(option)) == 0)		\
>> -		tmp = strict_strtol((char *)p + strlen(option"="), 10, &res); \
>> +		tmp = kstrtou32((char *)p + strlen(option"="), 10, &res); \
>>   } while (0)
>>
>>   void __init prom_init_env(void)
>>   {
>>   	/* pmon passes arguments in 32bit pointers */
>> -	int *_prom_envp;
>> -	unsigned long bus_clock;
>>   	unsigned int processor_id;
>> +
>> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
>> +	int *_prom_envp;
>>   	long l;
>>
>>   	/* firmware arguments are initialized in head.S */
>> @@ -48,7 +56,6 @@ void __init prom_init_env(void)
>>
>>   	l = (long)*_prom_envp;
>>   	while (l != 0) {
>> -		parse_even_earlier(bus_clock, "busclock", l);
>>   		parse_even_earlier(cpu_clock_freq, "cpuclock", l);
>>   		parse_even_earlier(memsize, "memsize", l);
>>   		parse_even_earlier(highmemsize, "highmemsize", l);
>> @@ -57,8 +64,38 @@ void __init prom_init_env(void)
>>   	}
>>   	if (memsize == 0)
>>   		memsize = 256;
>> -	if (bus_clock == 0)
>> -		bus_clock = 66000000;
>> +	pr_info("memsize=%ld, highmemsize=%ld\n", memsize, highmemsize);
>> +#else
>> +	/* firmware arguments are initialized in head.S */
>> +	boot_p = (struct boot_params *)fw_arg2;
>> +	loongson_p = &(boot_p->efi.smbios.lp);
>> +
>> +	ecpu = (struct efi_cpuinfo_loongson *)
>> +		((u64)loongson_p + loongson_p->cpu_offset);
>> +	emap = (struct efi_memory_map_loongson *)
>> +		((u64)loongson_p + loongson_p->memory_offset);
>> +	eirq_source = (struct irq_source_routing_table *)
>> +		((u64)loongson_p + loongson_p->irq_offset);
>> +
>> +	cpu_clock_freq = ecpu->cpu_clock_freq;
>> +	loongson_sysconf.cputype = ecpu->cputype;
>> +	loongson_sysconf.nr_cpus = ecpu->nr_cpus;
>> +	if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
>> +		loongson_sysconf.nr_cpus = NR_CPUS;
>> +
>> +	loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr;
>> +	loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
>> +	loongson_sysconf.pci_io_base = eirq_source->pci_io_start_addr;
>> +
>> +	loongson_sysconf.restart_addr = boot_p->reset_system.ResetWarm;
>> +	loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
>> +
>> +	loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
>> +	loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios;
>> +	pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
>> +		loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
>> +		loongson_sysconf.vgabios_addr);
>> +#endif
>>   	if (cpu_clock_freq == 0) {
>>   		processor_id = (&current_cpu_data)->processor_id;
>>   		switch (processor_id & PRID_REV_MASK) {
>> @@ -68,12 +105,13 @@ void __init prom_init_env(void)
>>   		case PRID_REV_LOONGSON2F:
>>   			cpu_clock_freq = 797000000;
>>   			break;
>> +		case PRID_REV_LOONGSON3A:
>> +			cpu_clock_freq = 900000000;
>> +			break;
>>   		default:
>>   			cpu_clock_freq = 100000000;
>>   			break;
>>   		}
>>   	}
>> -
>> -	pr_info("busclock=%ld, cpuclock=%ld, memsize=%ld, highmemsize=%ld\n",
>> -		bus_clock, cpu_clock_freq, memsize, highmemsize);
>> +	pr_info("CpuClock = %u\n", cpu_clock_freq);
>>   }
>> diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
>> index ae7af1f..81ba3b4 100644
>> --- a/arch/mips/loongson/common/init.c
>> +++ b/arch/mips/loongson/common/init.c
>> @@ -17,10 +17,6 @@ unsigned long __maybe_unused _loongson_addrwincfg_base;
>>
>>   void __init prom_init(void)
>>   {
>> -	/* init base address of io space */
>> -	set_io_port_base((unsigned long)
>> -		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
>> -
>>   #ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
>>   	_loongson_addrwincfg_base = (unsigned long)
>>   		ioremap(LOONGSON_ADDRWINCFG_BASE, LOONGSON_ADDRWINCFG_SIZE);
>> @@ -28,6 +24,11 @@ void __init prom_init(void)
>>
>>   	prom_init_cmdline();
>>   	prom_init_env();
>> +
>> +	/* init base address of io space */
>> +	set_io_port_base((unsigned long)
>> +		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
>> +
>>   	prom_init_memory();
>>
>>   	/*init the uart base address */
>> diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c
>> index 8626a42..42b2431 100644
>> --- a/arch/mips/loongson/common/mem.c
>> +++ b/arch/mips/loongson/common/mem.c
>> @@ -11,9 +11,14 @@
>>   #include <asm/bootinfo.h>
>>
>>   #include <loongson.h>
>> +#include <boot_param.h>
>>   #include <mem.h>
>>   #include <pci.h>
>>
>> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
>> +
>> +u32 memsize, highmemsize;
>> +
>>   void __init prom_init_memory(void)
>>   {
>>   	add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
>> @@ -49,6 +54,43 @@ void __init prom_init_memory(void)
>>   #endif /* !CONFIG_64BIT */
>>   }
>>
>> +#else /* CONFIG_LEFI_FIRMWARE_INTERFACE */
>> +
>> +void __init prom_init_memory(void)
>> +{
>> +	int i;
>> +	u32 node_id;
>> +	u32 mem_type;
>> +
>> +	/* parse memory information */
>> +	for (i = 0; i < emap->nr_map; i++) {
>> +		node_id = emap->map[i].node_id;
>> +		mem_type = emap->map[i].mem_type;
>> +
>> +		if (node_id == 0) {
>> +			switch (mem_type) {
>> +			case SYSTEM_RAM_LOW:
>> +				add_memory_region(emap->map[i].mem_start,
>> +					(u64)emap->map[i].mem_size << 20,
>> +					BOOT_MEM_RAM);
>> +				break;
>> +			case SYSTEM_RAM_HIGH:
>> +				add_memory_region(emap->map[i].mem_start,
>> +					(u64)emap->map[i].mem_size << 20,
>> +					BOOT_MEM_RAM);
>> +				break;
>> +			case MEM_RESERVED:
>> +				add_memory_region(emap->map[i].mem_start,
>> +					(u64)emap->map[i].mem_size << 20,
>> +					BOOT_MEM_RESERVED);
>> +				break;
>> +			}
>> +		}
>> +	}
>> +}
>> +
>> +#endif /* CONFIG_LEFI_FIRMWARE_INTERFACE */
>> +
>>   /* override of arch/mips/mm/cache.c: __uncached_access */
>>   int __uncached_access(struct file *file, unsigned long addr)
>>   {
>> diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson/common/pci.c
>> index fa77844..003ab4e 100644
>> --- a/arch/mips/loongson/common/pci.c
>> +++ b/arch/mips/loongson/common/pci.c
>> @@ -11,6 +11,7 @@
>>
>>   #include <pci.h>
>>   #include <loongson.h>
>> +#include <boot_param.h>
>>
>>   static struct resource loongson_pci_mem_resource = {
>>   	.name	= "pci memory space",
>> @@ -82,7 +83,10 @@ static int __init pcibios_init(void)
>>   	setup_pcimap();
>>
>>   	loongson_pci_controller.io_map_base = mips_io_port_base;
>> -
>> +#ifdef CONFIG_LEFI_FIRMWARE_INTERFACE
>> +	loongson_pci_mem_resource.start = loongson_sysconf.pci_mem_start_addr;
>> +	loongson_pci_mem_resource.end = loongson_sysconf.pci_mem_end_addr;
>> +#endif
>>   	register_pci_controller(&loongson_pci_controller);
>>
>>   	return 0;
>> diff --git a/arch/mips/loongson/common/reset.c b/arch/mips/loongson/common/reset.c
>> index 65bfbb5..a60715e 100644
>> --- a/arch/mips/loongson/common/reset.c
>> +++ b/arch/mips/loongson/common/reset.c
>> @@ -16,6 +16,7 @@
>>   #include <asm/reboot.h>
>>
>>   #include <loongson.h>
>> +#include <boot_param.h>
>>
>>   static inline void loongson_reboot(void)
>>   {
>> @@ -37,17 +38,37 @@ static inline void loongson_reboot(void)
>>
>>   static void loongson_restart(char *command)
>>   {
>> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
>>   	/* do preparation for reboot */
>>   	mach_prepare_reboot();
>>
>>   	/* reboot via jumping to boot base address */
>>   	loongson_reboot();
>> +#else
>> +	void (*fw_restart)(void) = (void *)loongson_sysconf.restart_addr;
>> +
>> +	fw_restart();
>> +	while (1) {
>> +		if (cpu_wait)
>> +			cpu_wait();
>> +	}
>> +#endif
>>   }
>>
>>   static void loongson_poweroff(void)
>>   {
>> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
>>   	mach_prepare_shutdown();
>>   	unreachable();
>> +#else
>> +	void (*fw_poweroff)(void) = (void *)loongson_sysconf.poweroff_addr;
>> +
>> +	fw_poweroff();
>> +	while (1) {
>> +		if (cpu_wait)
>> +			cpu_wait();
>> +	}
>> +#endif
>>   }
>>
>>   static void loongson_halt(void)
>> --
>> 1.7.7.3
>>
>>
>

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

* Re: [PATCH V16 04/12] MIPS: Loongson: Add UEFI-like firmware interface (LEFI) support
@ 2014-01-09 12:43       ` Alex Smith
  0 siblings, 0 replies; 55+ messages in thread
From: Alex Smith @ 2014-01-09 12:43 UTC (permalink / raw)
  To: Aurelien Jarno, Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On 08/01/14 22:58, Aurelien Jarno wrote:
> On Wed, Jan 08, 2014 at 10:44:20AM +0800, Huacai Chen wrote:
>> The new UEFI-like firmware interface (LEFI, i.e. Loongson Unified
>> Firmware Interface) has 3 advantages:
>>
>> 1, Firmware export a physical memory map which is similar to X86's
>>     E820 map, so prom_init_memory() will be more elegant that #ifdef
>>     clauses can be removed.
>> 2, Firmware export a pci irq routing table, we no longer need pci
>>     irq routing fixup in kernel's code.
>> 3, Firmware has a built-in vga bios, and its address is exported,
>>     the linux kernel no longer need an embedded blob.
>>
>> With the LEFI interface, Loongson-3A/2G and all their successors can use
>> a unified kernel. All Loongson-based machines support this new interface
>> except 2E/2F series.
>>
>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
>> Signed-off-by: Hongliang Tao <taohl@lemote.com>
>> Signed-off-by: Hua Yan <yanh@lemote.com>
>> ---
>>   arch/mips/include/asm/mach-loongson/boot_param.h |  159 ++++++++++++++++++++++
>>   arch/mips/include/asm/mach-loongson/loongson.h   |    4 +-
>>   arch/mips/loongson/common/env.c                  |   64 +++++++--
>>   arch/mips/loongson/common/init.c                 |    9 +-
>>   arch/mips/loongson/common/mem.c                  |   42 ++++++
>>   arch/mips/loongson/common/pci.c                  |    6 +-
>>   arch/mips/loongson/common/reset.c                |   21 +++
>>   7 files changed, 285 insertions(+), 20 deletions(-)
>>   create mode 100644 arch/mips/include/asm/mach-loongson/boot_param.h
>>
>> diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h
>> new file mode 100644
>> index 0000000..234c0eb
>> --- /dev/null
>> +++ b/arch/mips/include/asm/mach-loongson/boot_param.h
>> @@ -0,0 +1,159 @@
>> +#ifndef __ASM_MACH_LOONGSON_BOOT_PARAM_H_
>> +#define __ASM_MACH_LOONGSON_BOOT_PARAM_H_
>> +
>> +#define SYSTEM_RAM_LOW		1
>> +#define SYSTEM_RAM_HIGH		2
>> +#define MEM_RESERVED		3
>> +#define PCI_IO			4
>> +#define PCI_MEM			5
>> +#define LOONGSON_CFG_REG	6
>> +#define VIDEO_ROM		7
>> +#define ADAPTER_ROM		8
>> +#define ACPI_TABLE		9
>> +#define MAX_MEMORY_TYPE		10
>> +
>> +#define LOONGSON3_BOOT_MEM_MAP_MAX 128
>> +struct efi_memory_map_loongson {
>> +	u16 vers;	/* version of efi_memory_map */
>> +	u32 nr_map;	/* number of memory_maps */
>> +	u32 mem_freq;	/* memory frequence */
>> +	struct mem_map {
>> +		u32 node_id;	/* node_id which memory attached to */
>> +		u32 mem_type;	/* system memory, pci memory, pci io, etc. */
>> +		u64 mem_start;	/* memory map start address */
>> +		u32 mem_size;	/* each memory_map size, not the total size */
>> +	} map[LOONGSON3_BOOT_MEM_MAP_MAX];
>> +} __packed;
>> +
>> +enum loongson_cpu_type {
>> +	Loongson_2E = 0,
>> +	Loongson_2F = 1,
>> +	Loongson_3A = 2,
>> +	Loongson_3B = 3,
>> +	Loongson_1A = 4,
>> +	Loongson_1B = 5
>> +};
>> +
>> +/*
>> + * Capability and feature descriptor structure for MIPS CPU
>> + */
>> +struct efi_cpuinfo_loongson {
>> +	u16 vers;     /* version of efi_cpuinfo_loongson */
>> +	u32 processor_id; /* PRID, e.g. 6305, 6306 */
>> +	u32 cputype;  /* Loongson_3A/3B, etc. */
>> +	u32 total_node;   /* num of total numa nodes */
>> +	u32 cpu_startup_core_id; /* Core id */
>> +	u32 cpu_clock_freq; /* cpu_clock */
>> +	u32 nr_cpus;
>> +} __packed;
>> +
>> +struct system_loongson {
>> +	u16 vers;     /* version of system_loongson */
>> +	u32 ccnuma_smp; /* 0: no numa; 1: has numa */
>> +	u32 sing_double_channel; /* 1:single; 2:double */
>> +} __packed;
>> +
>> +struct irq_source_routing_table {
>> +	u16 vers;
>> +	u16 size;
>> +	u16 rtr_bus;
>> +	u16 rtr_devfn;
>> +	u32 vendor;
>> +	u32 device;
>> +	u32 PIC_type;   /* conform use HT or PCI to route to CPU-PIC */
>> +	u64 ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */
>> +	u64 ht_enable;  /* irqs used in this PIC */
>> +	u32 node_id;    /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */
>> +	u64 pci_mem_start_addr;
>> +	u64 pci_mem_end_addr;
>> +	u64 pci_io_start_addr;
>> +	u64 pci_io_end_addr;
>> +	u64 pci_config_addr;
>> +} __packed;
>> +
>> +struct interface_info {
>> +	u16 vers; /* version of the specificition */
>> +	u16 size;
>> +	u8  flag;
>> +	char description[64];
>> +} __packed;
>> +
>> +#define MAX_RESOURCE_NUMBER 128
>> +struct resource_loongson {
>> +	u64 start; /* resource start address */
>> +	u64 end;   /* resource end address */
>> +	char name[64];
>> +	u32 flags;
>> +};
>> +
>> +struct archdev_data {};  /* arch specific additions */
>> +
>> +struct board_devices {
>> +	char name[64];    /* hold the device name */
>> +	u32 num_resources; /* number of device_resource */
>> +	/* for each device's resource */
>> +	struct resource_loongson resource[MAX_RESOURCE_NUMBER];
>> +	/* arch specific additions */
>> +	struct archdev_data archdata;
>> +};
>> +
>> +struct loongson_special_attribute {
>> +	u16 vers;     /* version of this special */
>> +	char special_name[64]; /* special_atribute_name */
>> +	u32 loongson_special_type; /* type of special device */
>> +	/* for each device's resource */
>> +	struct resource_loongson resource[MAX_RESOURCE_NUMBER];
>> +};
>> +
>> +struct loongson_params {
>> +	u64 memory_offset;	/* efi_memory_map_loongson struct offset */
>> +	u64 cpu_offset;		/* efi_cpuinfo_loongson struct offset */
>> +	u64 system_offset;	/* system_loongson struct offset */
>> +	u64 irq_offset;		/* irq_source_routing_table struct offset */
>> +	u64 interface_offset;	/* interface_info struct offset */
>> +	u64 special_offset;	/* loongson_special_attribute struct offset */
>> +	u64 boarddev_table_offset;  /* board_devices offset */
>> +};
>> +
>> +struct smbios_tables {
>> +	u16 vers;     /* version of smbios */
>> +	u64 vga_bios; /* vga_bios address */
>> +	struct loongson_params lp;
>> +};
>> +
>> +struct efi_reset_system_t {
>> +	u64 ResetCold;
>> +	u64 ResetWarm;
>> +	u64 ResetType;
>> +	u64 Shutdown;
>> +};
>> +
>> +struct efi_loongson {
>> +	u64 mps;	/* MPS table */
>> +	u64 acpi;	/* ACPI table (IA64 ext 0.71) */
>> +	u64 acpi20;	/* ACPI table (ACPI 2.0) */
>> +	struct smbios_tables smbios;	/* SM BIOS table */
>> +	u64 sal_systab;	/* SAL system table */
>> +	u64 boot_info;	/* boot info table */
>> +};
>> +
>> +struct boot_params {
>> +	struct efi_loongson efi;
>> +	struct efi_reset_system_t reset_system;
>> +};
>> +
>> +struct loongson_system_configuration {
>> +	u32 nr_cpus;
>> +	enum loongson_cpu_type cputype;
>> +	u64 ht_control_base;
>> +	u64 pci_mem_start_addr;
>> +	u64 pci_mem_end_addr;
>> +	u64 pci_io_base;
>> +	u64 restart_addr;
>> +	u64 poweroff_addr;
>> +	u64 vgabios_addr;
>> +};
>> +
>> +extern struct efi_memory_map_loongson *emap;
>> +extern struct loongson_system_configuration loongson_sysconf;
>
> Thanks a lot for the loongson_sysconf struct, it looks a lot more clean
> now. What about emap? Isn't there any risk that the kernel reuse the
> corresponding memory and that its content is lost? It should be possible
> to hold a copy of this struct in loongson_sysconf.

I would guess that it won't be overwritten while it's still needed, 
since it is used to add memory regions in mem.c and then not used after 
that.

I wonder if it may be nicer to also add the emap pointer to 
loongson_sysconf to avoid having an extra global, or if not, at least 
rename it to a more descriptive name, such as loongson_memmap.

Alex

>
>
>> +#endif
>> diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
>> index b286534..5913ea0 100644
>> --- a/arch/mips/include/asm/mach-loongson/loongson.h
>> +++ b/arch/mips/include/asm/mach-loongson/loongson.h
>> @@ -24,8 +24,8 @@ extern void mach_prepare_reboot(void);
>>   extern void mach_prepare_shutdown(void);
>>
>>   /* environment arguments from bootloader */
>> -extern unsigned long cpu_clock_freq;
>> -extern unsigned long memsize, highmemsize;
>> +extern u32 cpu_clock_freq;
>> +extern u32 memsize, highmemsize;
>>
>>   /* loongson-specific command line, env and memory initialization */
>>   extern void __init prom_init_memory(void);
>> diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
>> index 0a18fcf..ba2b6df 100644
>> --- a/arch/mips/loongson/common/env.c
>> +++ b/arch/mips/loongson/common/env.c
>> @@ -18,29 +18,37 @@
>>    * option) any later version.
>>    */
>>   #include <linux/module.h>
>> -
>>   #include <asm/bootinfo.h>
>> -
>>   #include <loongson.h>
>> +#include <boot_param.h>
>> +
>> +struct boot_params *boot_p;
>> +struct loongson_params *loongson_p;
>> +
>> +struct efi_cpuinfo_loongson *ecpu;
>> +struct efi_memory_map_loongson *emap;
>> +struct system_loongson *esys;
>> +struct irq_source_routing_table *eirq_source;
>> +struct loongson_system_configuration loongson_sysconf;
>>
>> -unsigned long cpu_clock_freq;
>> +u32 cpu_clock_freq;
>>   EXPORT_SYMBOL(cpu_clock_freq);
>> -unsigned long memsize, highmemsize;
>>
>>   #define parse_even_earlier(res, option, p)				\
>>   do {									\
>>   	unsigned int tmp __maybe_unused;				\
>>   									\
>>   	if (strncmp(option, (char *)p, strlen(option)) == 0)		\
>> -		tmp = strict_strtol((char *)p + strlen(option"="), 10, &res); \
>> +		tmp = kstrtou32((char *)p + strlen(option"="), 10, &res); \
>>   } while (0)
>>
>>   void __init prom_init_env(void)
>>   {
>>   	/* pmon passes arguments in 32bit pointers */
>> -	int *_prom_envp;
>> -	unsigned long bus_clock;
>>   	unsigned int processor_id;
>> +
>> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
>> +	int *_prom_envp;
>>   	long l;
>>
>>   	/* firmware arguments are initialized in head.S */
>> @@ -48,7 +56,6 @@ void __init prom_init_env(void)
>>
>>   	l = (long)*_prom_envp;
>>   	while (l != 0) {
>> -		parse_even_earlier(bus_clock, "busclock", l);
>>   		parse_even_earlier(cpu_clock_freq, "cpuclock", l);
>>   		parse_even_earlier(memsize, "memsize", l);
>>   		parse_even_earlier(highmemsize, "highmemsize", l);
>> @@ -57,8 +64,38 @@ void __init prom_init_env(void)
>>   	}
>>   	if (memsize == 0)
>>   		memsize = 256;
>> -	if (bus_clock == 0)
>> -		bus_clock = 66000000;
>> +	pr_info("memsize=%ld, highmemsize=%ld\n", memsize, highmemsize);
>> +#else
>> +	/* firmware arguments are initialized in head.S */
>> +	boot_p = (struct boot_params *)fw_arg2;
>> +	loongson_p = &(boot_p->efi.smbios.lp);
>> +
>> +	ecpu = (struct efi_cpuinfo_loongson *)
>> +		((u64)loongson_p + loongson_p->cpu_offset);
>> +	emap = (struct efi_memory_map_loongson *)
>> +		((u64)loongson_p + loongson_p->memory_offset);
>> +	eirq_source = (struct irq_source_routing_table *)
>> +		((u64)loongson_p + loongson_p->irq_offset);
>> +
>> +	cpu_clock_freq = ecpu->cpu_clock_freq;
>> +	loongson_sysconf.cputype = ecpu->cputype;
>> +	loongson_sysconf.nr_cpus = ecpu->nr_cpus;
>> +	if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
>> +		loongson_sysconf.nr_cpus = NR_CPUS;
>> +
>> +	loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr;
>> +	loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
>> +	loongson_sysconf.pci_io_base = eirq_source->pci_io_start_addr;
>> +
>> +	loongson_sysconf.restart_addr = boot_p->reset_system.ResetWarm;
>> +	loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
>> +
>> +	loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
>> +	loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios;
>> +	pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
>> +		loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
>> +		loongson_sysconf.vgabios_addr);
>> +#endif
>>   	if (cpu_clock_freq == 0) {
>>   		processor_id = (&current_cpu_data)->processor_id;
>>   		switch (processor_id & PRID_REV_MASK) {
>> @@ -68,12 +105,13 @@ void __init prom_init_env(void)
>>   		case PRID_REV_LOONGSON2F:
>>   			cpu_clock_freq = 797000000;
>>   			break;
>> +		case PRID_REV_LOONGSON3A:
>> +			cpu_clock_freq = 900000000;
>> +			break;
>>   		default:
>>   			cpu_clock_freq = 100000000;
>>   			break;
>>   		}
>>   	}
>> -
>> -	pr_info("busclock=%ld, cpuclock=%ld, memsize=%ld, highmemsize=%ld\n",
>> -		bus_clock, cpu_clock_freq, memsize, highmemsize);
>> +	pr_info("CpuClock = %u\n", cpu_clock_freq);
>>   }
>> diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
>> index ae7af1f..81ba3b4 100644
>> --- a/arch/mips/loongson/common/init.c
>> +++ b/arch/mips/loongson/common/init.c
>> @@ -17,10 +17,6 @@ unsigned long __maybe_unused _loongson_addrwincfg_base;
>>
>>   void __init prom_init(void)
>>   {
>> -	/* init base address of io space */
>> -	set_io_port_base((unsigned long)
>> -		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
>> -
>>   #ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
>>   	_loongson_addrwincfg_base = (unsigned long)
>>   		ioremap(LOONGSON_ADDRWINCFG_BASE, LOONGSON_ADDRWINCFG_SIZE);
>> @@ -28,6 +24,11 @@ void __init prom_init(void)
>>
>>   	prom_init_cmdline();
>>   	prom_init_env();
>> +
>> +	/* init base address of io space */
>> +	set_io_port_base((unsigned long)
>> +		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
>> +
>>   	prom_init_memory();
>>
>>   	/*init the uart base address */
>> diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c
>> index 8626a42..42b2431 100644
>> --- a/arch/mips/loongson/common/mem.c
>> +++ b/arch/mips/loongson/common/mem.c
>> @@ -11,9 +11,14 @@
>>   #include <asm/bootinfo.h>
>>
>>   #include <loongson.h>
>> +#include <boot_param.h>
>>   #include <mem.h>
>>   #include <pci.h>
>>
>> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
>> +
>> +u32 memsize, highmemsize;
>> +
>>   void __init prom_init_memory(void)
>>   {
>>   	add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
>> @@ -49,6 +54,43 @@ void __init prom_init_memory(void)
>>   #endif /* !CONFIG_64BIT */
>>   }
>>
>> +#else /* CONFIG_LEFI_FIRMWARE_INTERFACE */
>> +
>> +void __init prom_init_memory(void)
>> +{
>> +	int i;
>> +	u32 node_id;
>> +	u32 mem_type;
>> +
>> +	/* parse memory information */
>> +	for (i = 0; i < emap->nr_map; i++) {
>> +		node_id = emap->map[i].node_id;
>> +		mem_type = emap->map[i].mem_type;
>> +
>> +		if (node_id == 0) {
>> +			switch (mem_type) {
>> +			case SYSTEM_RAM_LOW:
>> +				add_memory_region(emap->map[i].mem_start,
>> +					(u64)emap->map[i].mem_size << 20,
>> +					BOOT_MEM_RAM);
>> +				break;
>> +			case SYSTEM_RAM_HIGH:
>> +				add_memory_region(emap->map[i].mem_start,
>> +					(u64)emap->map[i].mem_size << 20,
>> +					BOOT_MEM_RAM);
>> +				break;
>> +			case MEM_RESERVED:
>> +				add_memory_region(emap->map[i].mem_start,
>> +					(u64)emap->map[i].mem_size << 20,
>> +					BOOT_MEM_RESERVED);
>> +				break;
>> +			}
>> +		}
>> +	}
>> +}
>> +
>> +#endif /* CONFIG_LEFI_FIRMWARE_INTERFACE */
>> +
>>   /* override of arch/mips/mm/cache.c: __uncached_access */
>>   int __uncached_access(struct file *file, unsigned long addr)
>>   {
>> diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson/common/pci.c
>> index fa77844..003ab4e 100644
>> --- a/arch/mips/loongson/common/pci.c
>> +++ b/arch/mips/loongson/common/pci.c
>> @@ -11,6 +11,7 @@
>>
>>   #include <pci.h>
>>   #include <loongson.h>
>> +#include <boot_param.h>
>>
>>   static struct resource loongson_pci_mem_resource = {
>>   	.name	= "pci memory space",
>> @@ -82,7 +83,10 @@ static int __init pcibios_init(void)
>>   	setup_pcimap();
>>
>>   	loongson_pci_controller.io_map_base = mips_io_port_base;
>> -
>> +#ifdef CONFIG_LEFI_FIRMWARE_INTERFACE
>> +	loongson_pci_mem_resource.start = loongson_sysconf.pci_mem_start_addr;
>> +	loongson_pci_mem_resource.end = loongson_sysconf.pci_mem_end_addr;
>> +#endif
>>   	register_pci_controller(&loongson_pci_controller);
>>
>>   	return 0;
>> diff --git a/arch/mips/loongson/common/reset.c b/arch/mips/loongson/common/reset.c
>> index 65bfbb5..a60715e 100644
>> --- a/arch/mips/loongson/common/reset.c
>> +++ b/arch/mips/loongson/common/reset.c
>> @@ -16,6 +16,7 @@
>>   #include <asm/reboot.h>
>>
>>   #include <loongson.h>
>> +#include <boot_param.h>
>>
>>   static inline void loongson_reboot(void)
>>   {
>> @@ -37,17 +38,37 @@ static inline void loongson_reboot(void)
>>
>>   static void loongson_restart(char *command)
>>   {
>> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
>>   	/* do preparation for reboot */
>>   	mach_prepare_reboot();
>>
>>   	/* reboot via jumping to boot base address */
>>   	loongson_reboot();
>> +#else
>> +	void (*fw_restart)(void) = (void *)loongson_sysconf.restart_addr;
>> +
>> +	fw_restart();
>> +	while (1) {
>> +		if (cpu_wait)
>> +			cpu_wait();
>> +	}
>> +#endif
>>   }
>>
>>   static void loongson_poweroff(void)
>>   {
>> +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
>>   	mach_prepare_shutdown();
>>   	unreachable();
>> +#else
>> +	void (*fw_poweroff)(void) = (void *)loongson_sysconf.poweroff_addr;
>> +
>> +	fw_poweroff();
>> +	while (1) {
>> +		if (cpu_wait)
>> +			cpu_wait();
>> +	}
>> +#endif
>>   }
>>
>>   static void loongson_halt(void)
>> --
>> 1.7.7.3
>>
>>
>

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

* Re: [PATCH V16 06/12] MIPS: Loongson 3: Add IRQ init and dispatch support
@ 2014-01-09 12:52     ` Alex Smith
  0 siblings, 0 replies; 55+ messages in thread
From: Alex Smith @ 2014-01-09 12:52 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, Aurelien Jarno,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On 08/01/14 02:44, Huacai Chen wrote:
> IRQ routing path of Loongson-3:
> Devices(most) --> I8259 --> HT Controller --> IRQ Routing Table --> CPU
>                                                    ^
>                                                    |
> Device(legacy devices such as UART) --> Bonito ---|
>
> IRQ Routing Table route 32 INTs to CPU's INT0~INT3(IP2~IP5 of CP0), 32
> INTs include 16 HT INTs(mostly), 4 PCI INTs, 1 LPC INT, etc. IP6 is used
> for IPI and IP7 is used for internal MIPS timer. LOONGSON_INT_ROUTER_*
> are IRQ Routing Table registers.
>
> I8259 IRQs are 1:1 mapped to HT1 INTs. LOONGSON_HT1_* are configuration
> registers of HT1 controller.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>   arch/mips/include/asm/mach-loongson/irq.h      |   26 ++++++
>   arch/mips/include/asm/mach-loongson/loongson.h |   10 ++
>   arch/mips/loongson/Makefile                    |    6 ++
>   arch/mips/loongson/loongson-3/Makefile         |    4 +
>   arch/mips/loongson/loongson-3/irq.c            |  110 ++++++++++++++++++++++++
>   5 files changed, 156 insertions(+), 0 deletions(-)
>   create mode 100644 arch/mips/include/asm/mach-loongson/irq.h
>   create mode 100644 arch/mips/loongson/loongson-3/Makefile
>   create mode 100644 arch/mips/loongson/loongson-3/irq.c
>
> diff --git a/arch/mips/include/asm/mach-loongson/irq.h b/arch/mips/include/asm/mach-loongson/irq.h
> new file mode 100644
> index 0000000..5711e3b
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson/irq.h
> @@ -0,0 +1,26 @@
> +#ifndef __ASM_MACH_LOONGSON_IRQ_H_
> +#define __ASM_MACH_LOONGSON_IRQ_H_
> +
> +#include <boot_param.h>
> +
> +/* cpu core interrupt numbers */
> +#define MIPS_CPU_IRQ_BASE 56
> +
> +#ifdef CONFIG_CPU_LOONGSON3
> +
> +#define LOONGSON_UART_IRQ   (MIPS_CPU_IRQ_BASE + 2) /* UART */
> +#define LOONGSON_HT1_IRQ    (MIPS_CPU_IRQ_BASE + 3) /* HT1 */
> +#define LOONGSON_TIMER_IRQ  (MIPS_CPU_IRQ_BASE + 7) /* CPU Timer */
> +
> +#define LOONGSON_HT1_CFG_BASE		loongson_sysconf.ht_control_base
> +#define LOONGSON_HT1_INT_VECTOR_BASE	(LOONGSON_HT1_CFG_BASE + 0x80)
> +#define LOONGSON_HT1_INT_EN_BASE	(LOONGSON_HT1_CFG_BASE + 0xa0)
> +#define LOONGSON_HT1_INT_VECTOR(n)	\
> +		LOONGSON3_REG32(LOONGSON_HT1_INT_VECTOR_BASE, 4 * n)
> +#define LOONGSON_HT1_INTN_EN(n)		\
> +		LOONGSON3_REG32(LOONGSON_HT1_INT_EN_BASE, 4 * n)
> +
> +#endif
> +
> +#include_next <irq.h>
> +#endif /* __ASM_MACH_LOONGSON_IRQ_H_ */
> diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
> index f0367ff..69e9d9e 100644
> --- a/arch/mips/include/asm/mach-loongson/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson/loongson.h
> @@ -62,6 +62,12 @@ extern int mach_i8259_irq(void);
>   #define LOONGSON_REG(x) \
>   	(*(volatile u32 *)((char *)CKSEG1ADDR(LOONGSON_REG_BASE) + (x)))
>
> +#define LOONGSON3_REG8(base, x) \
> +	(*(volatile u8 *)((char *)TO_UNCAC(base) + (x)))
> +
> +#define LOONGSON3_REG32(base, x) \
> +	(*(volatile u32 *)((char *)TO_UNCAC(base) + (x)))
> +
>   #define LOONGSON_IRQ_BASE	32
>   #define LOONGSON2_PERFCNT_IRQ	(MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */
>
> @@ -87,6 +93,10 @@ static inline void do_perfcnt_IRQ(void)
>   #define LOONGSON_REG_BASE	0x1fe00000
>   #define LOONGSON_REG_SIZE	0x00100000	/* 256Bytes + 256Bytes + ??? */
>   #define LOONGSON_REG_TOP	(LOONGSON_REG_BASE+LOONGSON_REG_SIZE-1)
> +/* Loongson-3 specific registers */
> +#define LOONGSON3_REG_BASE	0x3ff00000
> +#define LOONGSON3_REG_SIZE	0x00100000	/* 256Bytes + 256Bytes + ??? */
> +#define LOONGSON3_REG_TOP	(LOONGSON3_REG_BASE+LOONGSON3_REG_SIZE-1)
>
>   #define LOONGSON_LIO1_BASE	0x1ff00000
>   #define LOONGSON_LIO1_SIZE	0x00100000	/* 1M */
> diff --git a/arch/mips/loongson/Makefile b/arch/mips/loongson/Makefile
> index 0dc0055..7429994 100644
> --- a/arch/mips/loongson/Makefile
> +++ b/arch/mips/loongson/Makefile
> @@ -15,3 +15,9 @@ obj-$(CONFIG_LEMOTE_FULOONG2E)	+= fuloong-2e/
>   #
>
>   obj-$(CONFIG_LEMOTE_MACH2F)  += lemote-2f/
> +
> +#
> +# All Loongson-3 family machines
> +#
> +
> +obj-$(CONFIG_CPU_LOONGSON3)  += loongson-3/
> diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
> new file mode 100644
> index 0000000..b9968cd
> --- /dev/null
> +++ b/arch/mips/loongson/loongson-3/Makefile
> @@ -0,0 +1,4 @@
> +#
> +# Makefile for Loongson-3 family machines
> +#
> +obj-y			+= irq.o
> diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
> new file mode 100644
> index 0000000..3b52d56
> --- /dev/null
> +++ b/arch/mips/loongson/loongson-3/irq.c
> @@ -0,0 +1,110 @@
> +#include <loongson.h>
> +#include <irq.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +
> +#include <asm/irq_cpu.h>
> +#include <asm/i8259.h>
> +#include <asm/mipsregs.h>
> +
> +#define LOONGSON_INT_ROUTER_OFFSET	0x1400
> +#define LOONGSON_INT_ROUTER_INTEN	\
> +	  LOONGSON3_REG32(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + 0x24)
> +#define LOONGSON_INT_ROUTER_INTENSET	\
> +	  LOONGSON3_REG32(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + 0x28)
> +#define LOONGSON_INT_ROUTER_INTENCLR	\
> +	  LOONGSON3_REG32(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + 0x2c)
> +#define LOONGSON_INT_ROUTER_ENTRY(n)	\
> +	  LOONGSON3_REG8(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + n)
> +#define LOONGSON_INT_ROUTER_LPC		LOONGSON_INT_ROUTER_ENTRY(0x0a)
> +#define LOONGSON_INT_ROUTER_HT1(n)	LOONGSON_INT_ROUTER_ENTRY(n + 0x18)
> +
> +#define LOONGSON_INT_CORE0_INT0		0x11 /* route to int 0 of core 0 */
> +#define LOONGSON_INT_CORE0_INT1		0x21 /* route to int 1 of core 0 */

Move all of these definitions to irq.h? Half of the needed register 
definitions are added there above, and then half here, so it would make 
sense to have them all in one place.

> +
> +static void ht_irqdispatch(void)
> +{
> +	unsigned int i, irq;
> +	unsigned int ht_irq[] = {1, 3, 4, 5, 6, 7, 8, 12, 14, 15};
> +
> +	irq = LOONGSON_HT1_INT_VECTOR(0);
> +	LOONGSON_HT1_INT_VECTOR(0) = irq; /* Acknowledge the IRQs */
> +
> +	for (i = 0; i < (sizeof(ht_irq) / sizeof(*ht_irq)); i++) {

Can use ARRAY_SIZE here.

> +		if (irq & (0x1 << ht_irq[i]))
> +			do_IRQ(ht_irq[i]);
> +	}
> +}
> +
> +void mach_irq_dispatch(unsigned int pending)
> +{
> +	if (pending & CAUSEF_IP7)
> +		do_IRQ(LOONGSON_TIMER_IRQ);
> +	else if (pending & CAUSEF_IP3)
> +		ht_irqdispatch();
> +	else if (pending & CAUSEF_IP2)
> +		do_IRQ(LOONGSON_UART_IRQ);
> +	else {
> +		pr_err("%s : spurious interrupt\n", __func__);
> +		spurious_interrupt();
> +	}
> +}
> +
> +static struct irqaction cascade_irqaction = {
> +	.handler = no_action,
> +	.name = "cascade",
> +};
> +
> +static inline void mask_loongson_irq(struct irq_data *d)
> +{
> +	clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
> +	irq_disable_hazard();
> +}
> +
> +static inline void unmask_loongson_irq(struct irq_data *d)
> +{
> +	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
> +	irq_enable_hazard();
> +}
> +
> + /* For MIPS IRQs which shared by all cores */
> +static struct irq_chip loongson_irq_chip = {
> +	.name		= "Loongson",
> +	.irq_ack	= mask_loongson_irq,
> +	.irq_mask	= mask_loongson_irq,
> +	.irq_mask_ack	= mask_loongson_irq,
> +	.irq_unmask	= unmask_loongson_irq,
> +	.irq_eoi	= unmask_loongson_irq,
> +};
> +
> +void irq_router_init(void)
> +{
> +	int i;
> +
> +	/* route LPC int to cpu core0 int 0 */
> +	LOONGSON_INT_ROUTER_LPC = LOONGSON_INT_CORE0_INT0;
> +	/* route HT1 int0 ~ int7 to cpu core0 INT1*/
> +	for (i = 0; i < 8; i++)
> +		LOONGSON_INT_ROUTER_HT1(i) = LOONGSON_INT_CORE0_INT1;
> +	/* enable HT1 interrupt */
> +	LOONGSON_HT1_INTN_EN(0) = 0xffffffff;
> +	/* enable router interrupt intenset */
> +	LOONGSON_INT_ROUTER_INTENSET =
> +		LOONGSON_INT_ROUTER_INTEN | (0xffff << 16) | 0x1 << 10;
> +}

Add static to this function, it is not used anywhere else. Or even just 
fold it into mach_init_irq below, as it's not a particularly long function.

Thanks,
Alex

> +
> +void __init mach_init_irq(void)
> +{
> +	clear_c0_status(ST0_IM | ST0_BEV);
> +
> +	irq_router_init();
> +	mips_cpu_irq_init();
> +	init_i8259_irqs();
> +	irq_set_chip_and_handler(LOONGSON_UART_IRQ,
> +			&loongson_irq_chip, handle_level_irq);
> +
> +	/* setup HT1 irq */
> +	setup_irq(LOONGSON_HT1_IRQ, &cascade_irqaction);
> +
> +	set_c0_status(STATUSF_IP2 | STATUSF_IP6);
> +}
>

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

* Re: [PATCH V16 06/12] MIPS: Loongson 3: Add IRQ init and dispatch support
@ 2014-01-09 12:52     ` Alex Smith
  0 siblings, 0 replies; 55+ messages in thread
From: Alex Smith @ 2014-01-09 12:52 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, Aurelien Jarno,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On 08/01/14 02:44, Huacai Chen wrote:
> IRQ routing path of Loongson-3:
> Devices(most) --> I8259 --> HT Controller --> IRQ Routing Table --> CPU
>                                                    ^
>                                                    |
> Device(legacy devices such as UART) --> Bonito ---|
>
> IRQ Routing Table route 32 INTs to CPU's INT0~INT3(IP2~IP5 of CP0), 32
> INTs include 16 HT INTs(mostly), 4 PCI INTs, 1 LPC INT, etc. IP6 is used
> for IPI and IP7 is used for internal MIPS timer. LOONGSON_INT_ROUTER_*
> are IRQ Routing Table registers.
>
> I8259 IRQs are 1:1 mapped to HT1 INTs. LOONGSON_HT1_* are configuration
> registers of HT1 controller.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>   arch/mips/include/asm/mach-loongson/irq.h      |   26 ++++++
>   arch/mips/include/asm/mach-loongson/loongson.h |   10 ++
>   arch/mips/loongson/Makefile                    |    6 ++
>   arch/mips/loongson/loongson-3/Makefile         |    4 +
>   arch/mips/loongson/loongson-3/irq.c            |  110 ++++++++++++++++++++++++
>   5 files changed, 156 insertions(+), 0 deletions(-)
>   create mode 100644 arch/mips/include/asm/mach-loongson/irq.h
>   create mode 100644 arch/mips/loongson/loongson-3/Makefile
>   create mode 100644 arch/mips/loongson/loongson-3/irq.c
>
> diff --git a/arch/mips/include/asm/mach-loongson/irq.h b/arch/mips/include/asm/mach-loongson/irq.h
> new file mode 100644
> index 0000000..5711e3b
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson/irq.h
> @@ -0,0 +1,26 @@
> +#ifndef __ASM_MACH_LOONGSON_IRQ_H_
> +#define __ASM_MACH_LOONGSON_IRQ_H_
> +
> +#include <boot_param.h>
> +
> +/* cpu core interrupt numbers */
> +#define MIPS_CPU_IRQ_BASE 56
> +
> +#ifdef CONFIG_CPU_LOONGSON3
> +
> +#define LOONGSON_UART_IRQ   (MIPS_CPU_IRQ_BASE + 2) /* UART */
> +#define LOONGSON_HT1_IRQ    (MIPS_CPU_IRQ_BASE + 3) /* HT1 */
> +#define LOONGSON_TIMER_IRQ  (MIPS_CPU_IRQ_BASE + 7) /* CPU Timer */
> +
> +#define LOONGSON_HT1_CFG_BASE		loongson_sysconf.ht_control_base
> +#define LOONGSON_HT1_INT_VECTOR_BASE	(LOONGSON_HT1_CFG_BASE + 0x80)
> +#define LOONGSON_HT1_INT_EN_BASE	(LOONGSON_HT1_CFG_BASE + 0xa0)
> +#define LOONGSON_HT1_INT_VECTOR(n)	\
> +		LOONGSON3_REG32(LOONGSON_HT1_INT_VECTOR_BASE, 4 * n)
> +#define LOONGSON_HT1_INTN_EN(n)		\
> +		LOONGSON3_REG32(LOONGSON_HT1_INT_EN_BASE, 4 * n)
> +
> +#endif
> +
> +#include_next <irq.h>
> +#endif /* __ASM_MACH_LOONGSON_IRQ_H_ */
> diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
> index f0367ff..69e9d9e 100644
> --- a/arch/mips/include/asm/mach-loongson/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson/loongson.h
> @@ -62,6 +62,12 @@ extern int mach_i8259_irq(void);
>   #define LOONGSON_REG(x) \
>   	(*(volatile u32 *)((char *)CKSEG1ADDR(LOONGSON_REG_BASE) + (x)))
>
> +#define LOONGSON3_REG8(base, x) \
> +	(*(volatile u8 *)((char *)TO_UNCAC(base) + (x)))
> +
> +#define LOONGSON3_REG32(base, x) \
> +	(*(volatile u32 *)((char *)TO_UNCAC(base) + (x)))
> +
>   #define LOONGSON_IRQ_BASE	32
>   #define LOONGSON2_PERFCNT_IRQ	(MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */
>
> @@ -87,6 +93,10 @@ static inline void do_perfcnt_IRQ(void)
>   #define LOONGSON_REG_BASE	0x1fe00000
>   #define LOONGSON_REG_SIZE	0x00100000	/* 256Bytes + 256Bytes + ??? */
>   #define LOONGSON_REG_TOP	(LOONGSON_REG_BASE+LOONGSON_REG_SIZE-1)
> +/* Loongson-3 specific registers */
> +#define LOONGSON3_REG_BASE	0x3ff00000
> +#define LOONGSON3_REG_SIZE	0x00100000	/* 256Bytes + 256Bytes + ??? */
> +#define LOONGSON3_REG_TOP	(LOONGSON3_REG_BASE+LOONGSON3_REG_SIZE-1)
>
>   #define LOONGSON_LIO1_BASE	0x1ff00000
>   #define LOONGSON_LIO1_SIZE	0x00100000	/* 1M */
> diff --git a/arch/mips/loongson/Makefile b/arch/mips/loongson/Makefile
> index 0dc0055..7429994 100644
> --- a/arch/mips/loongson/Makefile
> +++ b/arch/mips/loongson/Makefile
> @@ -15,3 +15,9 @@ obj-$(CONFIG_LEMOTE_FULOONG2E)	+= fuloong-2e/
>   #
>
>   obj-$(CONFIG_LEMOTE_MACH2F)  += lemote-2f/
> +
> +#
> +# All Loongson-3 family machines
> +#
> +
> +obj-$(CONFIG_CPU_LOONGSON3)  += loongson-3/
> diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
> new file mode 100644
> index 0000000..b9968cd
> --- /dev/null
> +++ b/arch/mips/loongson/loongson-3/Makefile
> @@ -0,0 +1,4 @@
> +#
> +# Makefile for Loongson-3 family machines
> +#
> +obj-y			+= irq.o
> diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
> new file mode 100644
> index 0000000..3b52d56
> --- /dev/null
> +++ b/arch/mips/loongson/loongson-3/irq.c
> @@ -0,0 +1,110 @@
> +#include <loongson.h>
> +#include <irq.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +
> +#include <asm/irq_cpu.h>
> +#include <asm/i8259.h>
> +#include <asm/mipsregs.h>
> +
> +#define LOONGSON_INT_ROUTER_OFFSET	0x1400
> +#define LOONGSON_INT_ROUTER_INTEN	\
> +	  LOONGSON3_REG32(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + 0x24)
> +#define LOONGSON_INT_ROUTER_INTENSET	\
> +	  LOONGSON3_REG32(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + 0x28)
> +#define LOONGSON_INT_ROUTER_INTENCLR	\
> +	  LOONGSON3_REG32(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + 0x2c)
> +#define LOONGSON_INT_ROUTER_ENTRY(n)	\
> +	  LOONGSON3_REG8(LOONGSON3_REG_BASE, LOONGSON_INT_ROUTER_OFFSET + n)
> +#define LOONGSON_INT_ROUTER_LPC		LOONGSON_INT_ROUTER_ENTRY(0x0a)
> +#define LOONGSON_INT_ROUTER_HT1(n)	LOONGSON_INT_ROUTER_ENTRY(n + 0x18)
> +
> +#define LOONGSON_INT_CORE0_INT0		0x11 /* route to int 0 of core 0 */
> +#define LOONGSON_INT_CORE0_INT1		0x21 /* route to int 1 of core 0 */

Move all of these definitions to irq.h? Half of the needed register 
definitions are added there above, and then half here, so it would make 
sense to have them all in one place.

> +
> +static void ht_irqdispatch(void)
> +{
> +	unsigned int i, irq;
> +	unsigned int ht_irq[] = {1, 3, 4, 5, 6, 7, 8, 12, 14, 15};
> +
> +	irq = LOONGSON_HT1_INT_VECTOR(0);
> +	LOONGSON_HT1_INT_VECTOR(0) = irq; /* Acknowledge the IRQs */
> +
> +	for (i = 0; i < (sizeof(ht_irq) / sizeof(*ht_irq)); i++) {

Can use ARRAY_SIZE here.

> +		if (irq & (0x1 << ht_irq[i]))
> +			do_IRQ(ht_irq[i]);
> +	}
> +}
> +
> +void mach_irq_dispatch(unsigned int pending)
> +{
> +	if (pending & CAUSEF_IP7)
> +		do_IRQ(LOONGSON_TIMER_IRQ);
> +	else if (pending & CAUSEF_IP3)
> +		ht_irqdispatch();
> +	else if (pending & CAUSEF_IP2)
> +		do_IRQ(LOONGSON_UART_IRQ);
> +	else {
> +		pr_err("%s : spurious interrupt\n", __func__);
> +		spurious_interrupt();
> +	}
> +}
> +
> +static struct irqaction cascade_irqaction = {
> +	.handler = no_action,
> +	.name = "cascade",
> +};
> +
> +static inline void mask_loongson_irq(struct irq_data *d)
> +{
> +	clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
> +	irq_disable_hazard();
> +}
> +
> +static inline void unmask_loongson_irq(struct irq_data *d)
> +{
> +	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
> +	irq_enable_hazard();
> +}
> +
> + /* For MIPS IRQs which shared by all cores */
> +static struct irq_chip loongson_irq_chip = {
> +	.name		= "Loongson",
> +	.irq_ack	= mask_loongson_irq,
> +	.irq_mask	= mask_loongson_irq,
> +	.irq_mask_ack	= mask_loongson_irq,
> +	.irq_unmask	= unmask_loongson_irq,
> +	.irq_eoi	= unmask_loongson_irq,
> +};
> +
> +void irq_router_init(void)
> +{
> +	int i;
> +
> +	/* route LPC int to cpu core0 int 0 */
> +	LOONGSON_INT_ROUTER_LPC = LOONGSON_INT_CORE0_INT0;
> +	/* route HT1 int0 ~ int7 to cpu core0 INT1*/
> +	for (i = 0; i < 8; i++)
> +		LOONGSON_INT_ROUTER_HT1(i) = LOONGSON_INT_CORE0_INT1;
> +	/* enable HT1 interrupt */
> +	LOONGSON_HT1_INTN_EN(0) = 0xffffffff;
> +	/* enable router interrupt intenset */
> +	LOONGSON_INT_ROUTER_INTENSET =
> +		LOONGSON_INT_ROUTER_INTEN | (0xffff << 16) | 0x1 << 10;
> +}

Add static to this function, it is not used anywhere else. Or even just 
fold it into mach_init_irq below, as it's not a particularly long function.

Thanks,
Alex

> +
> +void __init mach_init_irq(void)
> +{
> +	clear_c0_status(ST0_IM | ST0_BEV);
> +
> +	irq_router_init();
> +	mips_cpu_irq_init();
> +	init_i8259_irqs();
> +	irq_set_chip_and_handler(LOONGSON_UART_IRQ,
> +			&loongson_irq_chip, handle_level_irq);
> +
> +	/* setup HT1 irq */
> +	setup_irq(LOONGSON_HT1_IRQ, &cascade_irqaction);
> +
> +	set_c0_status(STATUSF_IP2 | STATUSF_IP6);
> +}
>

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

* Re: [PATCH V16 08/12] MIPS: Loongson: Add swiotlb to support big memory (>4GB)
@ 2014-01-09 12:56     ` Alex Smith
  0 siblings, 0 replies; 55+ messages in thread
From: Alex Smith @ 2014-01-09 12:56 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, Aurelien Jarno,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On 08/01/14 02:44, Huacai Chen wrote:
> This is probably a workaround because Loongson doesn't support DMA
> address above 4GB. If memory is more than 4GB, CONFIG_SWIOTLB and
> ZONE_DMA32 should be selected. In this way, DMA pages are allocated
> below 4GB preferably.
>
> However, CONFIG_SWIOTLB+ZONE_DMA32 is not enough, so, we provide a
> platform-specific dma_map_ops::set_dma_mask() to make sure each
> driver's dma_mask and coherent_dma_mask is below 32-bit.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>   arch/mips/include/asm/dma-mapping.h                |    5 +
>   .../mips/include/asm/mach-loongson/dma-coherence.h |   22 +++-
>   arch/mips/loongson/common/Makefile                 |    5 +
>   arch/mips/loongson/common/dma-swiotlb.c            |  165 ++++++++++++++++++++
>   4 files changed, 196 insertions(+), 1 deletions(-)
>   create mode 100644 arch/mips/loongson/common/dma-swiotlb.c
>
> diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
> index 84238c5..06412aa 100644
> --- a/arch/mips/include/asm/dma-mapping.h
> +++ b/arch/mips/include/asm/dma-mapping.h
> @@ -49,9 +49,14 @@ static inline int dma_mapping_error(struct device *dev, u64 mask)
>   static inline int
>   dma_set_mask(struct device *dev, u64 mask)
>   {
> +	struct dma_map_ops *ops = get_dma_ops(dev);
> +
>   	if(!dev->dma_mask || !dma_supported(dev, mask))
>   		return -EIO;
>
> +	if (ops->set_dma_mask)
> +		return ops->set_dma_mask(dev, mask);
> +
>   	*dev->dma_mask = mask;
>
>   	return 0;
> diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
> index aeb2c05..6a90275 100644
> --- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
> +++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
> @@ -11,24 +11,40 @@
>   #ifndef __ASM_MACH_LOONGSON_DMA_COHERENCE_H
>   #define __ASM_MACH_LOONGSON_DMA_COHERENCE_H
>
> +#ifdef CONFIG_SWIOTLB
> +#include <linux/swiotlb.h>
> +#endif
> +
>   struct device;
>
> +extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
> +extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
>   static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
>   					  size_t size)
>   {
> +#ifdef CONFIG_CPU_LOONGSON3
> +	return virt_to_phys(addr);
> +#else
>   	return virt_to_phys(addr) | 0x80000000;
> +#endif
>   }
>
>   static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
>   					       struct page *page)
>   {
> +#ifdef CONFIG_CPU_LOONGSON3
> +	return page_to_phys(page);
> +#else
>   	return page_to_phys(page) | 0x80000000;
> +#endif
>   }
>
>   static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
>   	dma_addr_t dma_addr)
>   {
> -#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
> +#if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT)
> +	return dma_addr;
> +#elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
>   	return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff);
>   #else
>   	return dma_addr & 0x7fffffff;
> @@ -55,7 +71,11 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
>
>   static inline int plat_device_is_coherent(struct device *dev)
>   {
> +#ifdef CONFIG_DMA_NONCOHERENT
>   	return 0;
> +#else
> +	return 1;
> +#endif /* CONFIG_DMA_NONCOHERENT */
>   }
>
>   #endif /* __ASM_MACH_LOONGSON_DMA_COHERENCE_H */
> diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile
> index 9e4484c..0bb9cc9 100644
> --- a/arch/mips/loongson/common/Makefile
> +++ b/arch/mips/loongson/common/Makefile
> @@ -26,3 +26,8 @@ obj-$(CONFIG_CS5536) += cs5536/
>   #
>
>   obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
> +
> +#
> +# Big Memory (SWIOTLB) Support
> +#
> +obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o
> diff --git a/arch/mips/loongson/common/dma-swiotlb.c b/arch/mips/loongson/common/dma-swiotlb.c
> new file mode 100644
> index 0000000..9d5451b
> --- /dev/null
> +++ b/arch/mips/loongson/common/dma-swiotlb.c
> @@ -0,0 +1,165 @@
> +#include <linux/mm.h>
> +#include <linux/init.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/scatterlist.h>
> +#include <linux/swiotlb.h>
> +#include <linux/bootmem.h>
> +
> +#include <asm/bootinfo.h>
> +#include <dma-coherence.h>
> +
> +static void *loongson_dma_alloc_coherent(struct device *dev, size_t size,
> +		dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
> +{
> +	void *ret;
> +
> +	if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
> +		return ret;
> +
> +	/* ignore region specifiers */
> +	gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
> +
> +#ifdef CONFIG_ISA
> +	if (dev == NULL)
> +		gfp |= __GFP_DMA;
> +	else
> +#endif
> +#ifdef CONFIG_ZONE_DMA
> +	if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
> +		gfp |= __GFP_DMA;
> +	else
> +#endif
> +#ifdef CONFIG_ZONE_DMA32
> +	 /* Loongson-3 only support DMA in the memory below 4GB now */
> +	if (dev->coherent_dma_mask < DMA_BIT_MASK(40))
> +		gfp |= __GFP_DMA32;
> +	else
> +#endif
> +	;
> +	gfp |= __GFP_NORETRY;
> +
> +	ret = swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
> +	mb();
> +	return ret;
> +}
> +
> +static void loongson_dma_free_coherent(struct device *dev, size_t size,
> +		void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs)
> +{
> +	int order = get_order(size);
> +
> +	if (dma_release_from_coherent(dev, order, vaddr))
> +		return;
> +
> +	swiotlb_free_coherent(dev, size, vaddr, dma_handle);
> +}
> +
> +static dma_addr_t loongson_dma_map_page(struct device *dev, struct page *page,
> +				unsigned long offset, size_t size,
> +				enum dma_data_direction dir,
> +				struct dma_attrs *attrs)
> +{
> +	dma_addr_t daddr = swiotlb_map_page(dev, page, offset, size,
> +					dir, attrs);
> +	mb();
> +	return daddr;
> +}
> +
> +static int loongson_dma_map_sg(struct device *dev, struct scatterlist *sg,
> +				int nents, enum dma_data_direction dir,
> +				struct dma_attrs *attrs)
> +{
> +	int r = swiotlb_map_sg_attrs(dev, sg, nents, dir, NULL);
> +	mb();
> +
> +	return r;
> +}
> +
> +static void loongson_dma_sync_single_for_device(struct device *dev,
> +				dma_addr_t dma_handle, size_t size,
> +				enum dma_data_direction dir)
> +{
> +	swiotlb_sync_single_for_device(dev, dma_handle, size, dir);
> +	mb();
> +}
> +
> +static void loongson_dma_sync_sg_for_device(struct device *dev,
> +				struct scatterlist *sg, int nents,
> +				enum dma_data_direction dir)
> +{
> +	swiotlb_sync_sg_for_device(dev, sg, nents, dir);
> +	mb();
> +}
> +
> +static dma_addr_t
> +loongson_unity_phys_to_dma(struct device *dev, phys_addr_t paddr)
> +{
> +	return paddr;
> +}
> +
> +static phys_addr_t
> +loongson_unity_dma_to_phys(struct device *dev, dma_addr_t daddr)
> +{
> +	return daddr;
> +}
> +
> +struct loongson_dma_map_ops {
> +	struct dma_map_ops dma_map_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);
> +};
> +
> +dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
> +{
> +	struct loongson_dma_map_ops *ops = container_of(get_dma_ops(dev),
> +				struct loongson_dma_map_ops, dma_map_ops);
> +
> +	return ops->phys_to_dma(dev, paddr);
> +}
> +
> +phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
> +{
> +	struct loongson_dma_map_ops *ops = container_of(get_dma_ops(dev),
> +				struct loongson_dma_map_ops, dma_map_ops);
> +
> +	return ops->dma_to_phys(dev, daddr);
> +}

This seems a little bit convoluted. Since phys_to_dma and dma_to_phys 
will always end up calling the loongson_unity_ functions, I don't see 
any point in having the loongson_dma_map_ops structure to point to them. 
You can just implement phys_to_dma and dma_to_phys as inlines in 
mach-loongson/dma-coherence.h.

Thanks,
Alex

> +
> +static int loongson_dma_set_mask(struct device *dev, u64 mask)
> +{
> +	/* Loongson doesn't support DMA above 32-bit */
> +	if (mask > DMA_BIT_MASK(32)) {
> +		*dev->dma_mask = DMA_BIT_MASK(32);
> +		return -EIO;
> +	}
> +
> +	*dev->dma_mask = mask;
> +
> +	return 0;
> +}
> +
> +static struct loongson_dma_map_ops loongson_linear_dma_map_ops = {
> +	.dma_map_ops = {
> +		.alloc = loongson_dma_alloc_coherent,
> +		.free = loongson_dma_free_coherent,
> +		.map_page = loongson_dma_map_page,
> +		.unmap_page = swiotlb_unmap_page,
> +		.map_sg = loongson_dma_map_sg,
> +		.unmap_sg = swiotlb_unmap_sg_attrs,
> +		.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
> +		.sync_single_for_device = loongson_dma_sync_single_for_device,
> +		.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
> +		.sync_sg_for_device = loongson_dma_sync_sg_for_device,
> +		.mapping_error = swiotlb_dma_mapping_error,
> +		.dma_supported = swiotlb_dma_supported,
> +		.set_dma_mask = loongson_dma_set_mask
> +	},
> +	.phys_to_dma = loongson_unity_phys_to_dma,
> +	.dma_to_phys = loongson_unity_dma_to_phys
> +};
> +
> +void __init plat_swiotlb_setup(void)
> +{
> +	swiotlb_init(1);
> +	mips_dma_map_ops = &loongson_linear_dma_map_ops.dma_map_ops;
> +}
>

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

* Re: [PATCH V16 08/12] MIPS: Loongson: Add swiotlb to support big memory (>4GB)
@ 2014-01-09 12:56     ` Alex Smith
  0 siblings, 0 replies; 55+ messages in thread
From: Alex Smith @ 2014-01-09 12:56 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, Aurelien Jarno,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On 08/01/14 02:44, Huacai Chen wrote:
> This is probably a workaround because Loongson doesn't support DMA
> address above 4GB. If memory is more than 4GB, CONFIG_SWIOTLB and
> ZONE_DMA32 should be selected. In this way, DMA pages are allocated
> below 4GB preferably.
>
> However, CONFIG_SWIOTLB+ZONE_DMA32 is not enough, so, we provide a
> platform-specific dma_map_ops::set_dma_mask() to make sure each
> driver's dma_mask and coherent_dma_mask is below 32-bit.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>   arch/mips/include/asm/dma-mapping.h                |    5 +
>   .../mips/include/asm/mach-loongson/dma-coherence.h |   22 +++-
>   arch/mips/loongson/common/Makefile                 |    5 +
>   arch/mips/loongson/common/dma-swiotlb.c            |  165 ++++++++++++++++++++
>   4 files changed, 196 insertions(+), 1 deletions(-)
>   create mode 100644 arch/mips/loongson/common/dma-swiotlb.c
>
> diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
> index 84238c5..06412aa 100644
> --- a/arch/mips/include/asm/dma-mapping.h
> +++ b/arch/mips/include/asm/dma-mapping.h
> @@ -49,9 +49,14 @@ static inline int dma_mapping_error(struct device *dev, u64 mask)
>   static inline int
>   dma_set_mask(struct device *dev, u64 mask)
>   {
> +	struct dma_map_ops *ops = get_dma_ops(dev);
> +
>   	if(!dev->dma_mask || !dma_supported(dev, mask))
>   		return -EIO;
>
> +	if (ops->set_dma_mask)
> +		return ops->set_dma_mask(dev, mask);
> +
>   	*dev->dma_mask = mask;
>
>   	return 0;
> diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
> index aeb2c05..6a90275 100644
> --- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
> +++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
> @@ -11,24 +11,40 @@
>   #ifndef __ASM_MACH_LOONGSON_DMA_COHERENCE_H
>   #define __ASM_MACH_LOONGSON_DMA_COHERENCE_H
>
> +#ifdef CONFIG_SWIOTLB
> +#include <linux/swiotlb.h>
> +#endif
> +
>   struct device;
>
> +extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
> +extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
>   static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
>   					  size_t size)
>   {
> +#ifdef CONFIG_CPU_LOONGSON3
> +	return virt_to_phys(addr);
> +#else
>   	return virt_to_phys(addr) | 0x80000000;
> +#endif
>   }
>
>   static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
>   					       struct page *page)
>   {
> +#ifdef CONFIG_CPU_LOONGSON3
> +	return page_to_phys(page);
> +#else
>   	return page_to_phys(page) | 0x80000000;
> +#endif
>   }
>
>   static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
>   	dma_addr_t dma_addr)
>   {
> -#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
> +#if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT)
> +	return dma_addr;
> +#elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
>   	return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff);
>   #else
>   	return dma_addr & 0x7fffffff;
> @@ -55,7 +71,11 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
>
>   static inline int plat_device_is_coherent(struct device *dev)
>   {
> +#ifdef CONFIG_DMA_NONCOHERENT
>   	return 0;
> +#else
> +	return 1;
> +#endif /* CONFIG_DMA_NONCOHERENT */
>   }
>
>   #endif /* __ASM_MACH_LOONGSON_DMA_COHERENCE_H */
> diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile
> index 9e4484c..0bb9cc9 100644
> --- a/arch/mips/loongson/common/Makefile
> +++ b/arch/mips/loongson/common/Makefile
> @@ -26,3 +26,8 @@ obj-$(CONFIG_CS5536) += cs5536/
>   #
>
>   obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
> +
> +#
> +# Big Memory (SWIOTLB) Support
> +#
> +obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o
> diff --git a/arch/mips/loongson/common/dma-swiotlb.c b/arch/mips/loongson/common/dma-swiotlb.c
> new file mode 100644
> index 0000000..9d5451b
> --- /dev/null
> +++ b/arch/mips/loongson/common/dma-swiotlb.c
> @@ -0,0 +1,165 @@
> +#include <linux/mm.h>
> +#include <linux/init.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/scatterlist.h>
> +#include <linux/swiotlb.h>
> +#include <linux/bootmem.h>
> +
> +#include <asm/bootinfo.h>
> +#include <dma-coherence.h>
> +
> +static void *loongson_dma_alloc_coherent(struct device *dev, size_t size,
> +		dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
> +{
> +	void *ret;
> +
> +	if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
> +		return ret;
> +
> +	/* ignore region specifiers */
> +	gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
> +
> +#ifdef CONFIG_ISA
> +	if (dev == NULL)
> +		gfp |= __GFP_DMA;
> +	else
> +#endif
> +#ifdef CONFIG_ZONE_DMA
> +	if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
> +		gfp |= __GFP_DMA;
> +	else
> +#endif
> +#ifdef CONFIG_ZONE_DMA32
> +	 /* Loongson-3 only support DMA in the memory below 4GB now */
> +	if (dev->coherent_dma_mask < DMA_BIT_MASK(40))
> +		gfp |= __GFP_DMA32;
> +	else
> +#endif
> +	;
> +	gfp |= __GFP_NORETRY;
> +
> +	ret = swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
> +	mb();
> +	return ret;
> +}
> +
> +static void loongson_dma_free_coherent(struct device *dev, size_t size,
> +		void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs)
> +{
> +	int order = get_order(size);
> +
> +	if (dma_release_from_coherent(dev, order, vaddr))
> +		return;
> +
> +	swiotlb_free_coherent(dev, size, vaddr, dma_handle);
> +}
> +
> +static dma_addr_t loongson_dma_map_page(struct device *dev, struct page *page,
> +				unsigned long offset, size_t size,
> +				enum dma_data_direction dir,
> +				struct dma_attrs *attrs)
> +{
> +	dma_addr_t daddr = swiotlb_map_page(dev, page, offset, size,
> +					dir, attrs);
> +	mb();
> +	return daddr;
> +}
> +
> +static int loongson_dma_map_sg(struct device *dev, struct scatterlist *sg,
> +				int nents, enum dma_data_direction dir,
> +				struct dma_attrs *attrs)
> +{
> +	int r = swiotlb_map_sg_attrs(dev, sg, nents, dir, NULL);
> +	mb();
> +
> +	return r;
> +}
> +
> +static void loongson_dma_sync_single_for_device(struct device *dev,
> +				dma_addr_t dma_handle, size_t size,
> +				enum dma_data_direction dir)
> +{
> +	swiotlb_sync_single_for_device(dev, dma_handle, size, dir);
> +	mb();
> +}
> +
> +static void loongson_dma_sync_sg_for_device(struct device *dev,
> +				struct scatterlist *sg, int nents,
> +				enum dma_data_direction dir)
> +{
> +	swiotlb_sync_sg_for_device(dev, sg, nents, dir);
> +	mb();
> +}
> +
> +static dma_addr_t
> +loongson_unity_phys_to_dma(struct device *dev, phys_addr_t paddr)
> +{
> +	return paddr;
> +}
> +
> +static phys_addr_t
> +loongson_unity_dma_to_phys(struct device *dev, dma_addr_t daddr)
> +{
> +	return daddr;
> +}
> +
> +struct loongson_dma_map_ops {
> +	struct dma_map_ops dma_map_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);
> +};
> +
> +dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
> +{
> +	struct loongson_dma_map_ops *ops = container_of(get_dma_ops(dev),
> +				struct loongson_dma_map_ops, dma_map_ops);
> +
> +	return ops->phys_to_dma(dev, paddr);
> +}
> +
> +phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
> +{
> +	struct loongson_dma_map_ops *ops = container_of(get_dma_ops(dev),
> +				struct loongson_dma_map_ops, dma_map_ops);
> +
> +	return ops->dma_to_phys(dev, daddr);
> +}

This seems a little bit convoluted. Since phys_to_dma and dma_to_phys 
will always end up calling the loongson_unity_ functions, I don't see 
any point in having the loongson_dma_map_ops structure to point to them. 
You can just implement phys_to_dma and dma_to_phys as inlines in 
mach-loongson/dma-coherence.h.

Thanks,
Alex

> +
> +static int loongson_dma_set_mask(struct device *dev, u64 mask)
> +{
> +	/* Loongson doesn't support DMA above 32-bit */
> +	if (mask > DMA_BIT_MASK(32)) {
> +		*dev->dma_mask = DMA_BIT_MASK(32);
> +		return -EIO;
> +	}
> +
> +	*dev->dma_mask = mask;
> +
> +	return 0;
> +}
> +
> +static struct loongson_dma_map_ops loongson_linear_dma_map_ops = {
> +	.dma_map_ops = {
> +		.alloc = loongson_dma_alloc_coherent,
> +		.free = loongson_dma_free_coherent,
> +		.map_page = loongson_dma_map_page,
> +		.unmap_page = swiotlb_unmap_page,
> +		.map_sg = loongson_dma_map_sg,
> +		.unmap_sg = swiotlb_unmap_sg_attrs,
> +		.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
> +		.sync_single_for_device = loongson_dma_sync_single_for_device,
> +		.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
> +		.sync_sg_for_device = loongson_dma_sync_sg_for_device,
> +		.mapping_error = swiotlb_dma_mapping_error,
> +		.dma_supported = swiotlb_dma_supported,
> +		.set_dma_mask = loongson_dma_set_mask
> +	},
> +	.phys_to_dma = loongson_unity_phys_to_dma,
> +	.dma_to_phys = loongson_unity_dma_to_phys
> +};
> +
> +void __init plat_swiotlb_setup(void)
> +{
> +	swiotlb_init(1);
> +	mips_dma_map_ops = &loongson_linear_dma_map_ops.dma_map_ops;
> +}
>

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

* Re: [PATCH V16 09/12] MIPS: Loongson: Add Loongson-3 Kconfig options
@ 2014-01-09 13:07     ` Alex Smith
  0 siblings, 0 replies; 55+ messages in thread
From: Alex Smith @ 2014-01-09 13:07 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, Aurelien Jarno,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On 08/01/14 02:44, Huacai Chen wrote:
> Added Kconfig options include: Loongson-3 CPU and machine definition,
> CPU cache features, UEFI-like firmware interface (LEFI), HT-linked PCI,
> and big memory support.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>   arch/mips/Kconfig           |   29 +++++++++++++++++++++++++++-
>   arch/mips/loongson/Kconfig  |   44 +++++++++++++++++++++++++++++++++++++++++++
>   arch/mips/loongson/Platform |    1 +
>   3 files changed, 73 insertions(+), 1 deletions(-)
>
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index 17cc7ff..513e941 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -1487,6 +1487,18 @@ config CPU_LOONGSON2
>   	select CPU_SUPPORTS_HIGHMEM
>   	select CPU_SUPPORTS_HUGEPAGES
>
> +config CPU_LOONGSON3
> +	bool "Loongson 3 CPU"
> +	depends on SYS_HAS_CPU_LOONGSON3
> +	select CPU_SUPPORTS_64BIT_KERNEL
> +	select CPU_SUPPORTS_HIGHMEM
> +	select CPU_SUPPORTS_HUGEPAGES
> +	select WEAK_ORDERING
> +	select WEAK_REORDERING_BEYOND_LLSC
> +	help
> +		The Loongson 3 processor implements the MIPS III instruction set
> +		with many extensions.
> +

This should be moved into the "CPU type" choice block. Currently this 
appears as an option outside of that choice, and so it is possible to 
build a kernel without any CPU type selected.

Also, as Aurelien said on the previous version, shouldn't the comment be 
changed to MIPS64R2 rather than MIPS III even if you aren't selecting 
the MIPS64 CPU types for the time being? Note, if you replied to that 
comment I may not have seen it - I think the list is filtering your 
replies because they're HTML emails.

>   config CPU_LOONGSON1
>   	bool
>   	select CPU_MIPS32
> @@ -1513,6 +1526,10 @@ config SYS_HAS_CPU_LOONGSON2F
>   	select CPU_SUPPORTS_ADDRWINCFG if 64BIT
>   	select CPU_SUPPORTS_UNCACHED_ACCELERATED
>
> +config SYS_HAS_CPU_LOONGSON3
> +	bool
> +	select CPU_SUPPORTS_CPUFREQ
> +
>   config SYS_HAS_CPU_LOONGSON1B
>   	bool
>
> @@ -1703,7 +1720,7 @@ choice
>
>   config PAGE_SIZE_4KB
>   	bool "4kB"
> -	depends on !CPU_LOONGSON2
> +	depends on !CPU_LOONGSON2 && !CPU_LOONGSON3
>   	help
>   	 This option select the standard 4kB Linux page size.  On some
>   	 R3000-family processors this is the only available page size.  Using
> @@ -2373,6 +2390,16 @@ config PCI
>   	  your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
>   	  say Y, otherwise N.
>
> +config HT_PCI
> +	bool "Support for HT-linked PCI"
> +	depends on CPU_LOONGSON3
> +	select PCI_DOMAINS
> +	help
> +	  Loongson family machines use Hyper-Transport bus for inter-core
> +	  connection and device connection. The PCI bus is a subordinate
> +	  linked at HT. Choose Y unless you are using Loongson 2E/2F based
> +	  machines.
> +

Should this default to y, given that it is selected in the defconfig? 
Also, the comment referring to 2E/2F is redundant given that it depends 
on CPU_LOONGSON3 and cannot be selected on those machines.

>   config PCI_DOMAINS
>   	bool
>
> diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
> index 263beb9..4f3967c 100644
> --- a/arch/mips/loongson/Kconfig
> +++ b/arch/mips/loongson/Kconfig
> @@ -59,6 +59,33 @@ config LEMOTE_MACH2F
>
>   	  These family machines include fuloong2f mini PC, yeeloong2f notebook,
>   	  LingLoong allinone PC and so forth.
> +
> +config LEMOTE_MACH3A
> +	bool "Lemote Loongson 3A family machines"
> +	select ARCH_SPARSEMEM_ENABLE
> +	select GENERIC_ISA_DMA_SUPPORT_BROKEN
> +	select GENERIC_HARDIRQS_NO__DO_IRQ
> +	select BOOT_ELF32
> +	select BOARD_SCACHE
> +	select CSRC_R4K
> +	select CEVT_R4K
> +	select CPU_HAS_WB
> +	select HW_HAS_PCI
> +	select ISA
> +	select I8259
> +	select IRQ_CPU
> +	select SYS_HAS_CPU_LOONGSON3
> +	select SYS_HAS_EARLY_PRINTK
> +	select SYS_SUPPORTS_SMP
> +	select SYS_SUPPORTS_64BIT_KERNEL
> +	select SYS_SUPPORTS_HIGHMEM
> +	select SYS_SUPPORTS_LITTLE_ENDIAN
> +	select LOONGSON_MC146818
> +	select ZONE_DMA32 if 64BIT
> +	select LEFI_FIRMWARE_INTERFACE
> +	help
> +		Lemote Loongson 3A family machines utilize the 3A revision of
> +		Loongson processor and RS780/SBX00 chipset.
>   endchoice

Add "select NR_CPUS_DEFAULT_4" on here? Currently creating a 
configuration without using the loongson3_defconfig will default to 2, 
but unless I'm mistaken, all 3A machines are quad core?

>
>   config CS5536
> @@ -86,8 +114,24 @@ config LOONGSON_UART_BASE
>   	default y
>   	depends on EARLY_PRINTK || SERIAL_8250
>
> +config IOMMU_HELPER
> +	bool
> +
> +config NEED_SG_DMA_LENGTH
> +	bool
> +
> +config SWIOTLB
> +	bool "Soft IOMMU Support for Big Memory (>4GB)"
> +	depends on CPU_LOONGSON3
> +	select IOMMU_HELPER
> +	select NEED_SG_DMA_LENGTH
> +	select NEED_DMA_MAP_STATE
> +

Again, default to y?

Thanks,
Alex

>   config LOONGSON_MC146818
>   	bool
>   	default n
>
> +config LEFI_FIRMWARE_INTERFACE
> +	bool
> +
>   endif # MACH_LOONGSON
> diff --git a/arch/mips/loongson/Platform b/arch/mips/loongson/Platform
> index 29692e5..6205372 100644
> --- a/arch/mips/loongson/Platform
> +++ b/arch/mips/loongson/Platform
> @@ -30,3 +30,4 @@ platform-$(CONFIG_MACH_LOONGSON) += loongson/
>   cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely
>   load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000
>   load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000
> +load-$(CONFIG_CPU_LOONGSON3) += 0xffffffff80200000
>

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

* Re: [PATCH V16 09/12] MIPS: Loongson: Add Loongson-3 Kconfig options
@ 2014-01-09 13:07     ` Alex Smith
  0 siblings, 0 replies; 55+ messages in thread
From: Alex Smith @ 2014-01-09 13:07 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, Aurelien Jarno,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On 08/01/14 02:44, Huacai Chen wrote:
> Added Kconfig options include: Loongson-3 CPU and machine definition,
> CPU cache features, UEFI-like firmware interface (LEFI), HT-linked PCI,
> and big memory support.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>   arch/mips/Kconfig           |   29 +++++++++++++++++++++++++++-
>   arch/mips/loongson/Kconfig  |   44 +++++++++++++++++++++++++++++++++++++++++++
>   arch/mips/loongson/Platform |    1 +
>   3 files changed, 73 insertions(+), 1 deletions(-)
>
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index 17cc7ff..513e941 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -1487,6 +1487,18 @@ config CPU_LOONGSON2
>   	select CPU_SUPPORTS_HIGHMEM
>   	select CPU_SUPPORTS_HUGEPAGES
>
> +config CPU_LOONGSON3
> +	bool "Loongson 3 CPU"
> +	depends on SYS_HAS_CPU_LOONGSON3
> +	select CPU_SUPPORTS_64BIT_KERNEL
> +	select CPU_SUPPORTS_HIGHMEM
> +	select CPU_SUPPORTS_HUGEPAGES
> +	select WEAK_ORDERING
> +	select WEAK_REORDERING_BEYOND_LLSC
> +	help
> +		The Loongson 3 processor implements the MIPS III instruction set
> +		with many extensions.
> +

This should be moved into the "CPU type" choice block. Currently this 
appears as an option outside of that choice, and so it is possible to 
build a kernel without any CPU type selected.

Also, as Aurelien said on the previous version, shouldn't the comment be 
changed to MIPS64R2 rather than MIPS III even if you aren't selecting 
the MIPS64 CPU types for the time being? Note, if you replied to that 
comment I may not have seen it - I think the list is filtering your 
replies because they're HTML emails.

>   config CPU_LOONGSON1
>   	bool
>   	select CPU_MIPS32
> @@ -1513,6 +1526,10 @@ config SYS_HAS_CPU_LOONGSON2F
>   	select CPU_SUPPORTS_ADDRWINCFG if 64BIT
>   	select CPU_SUPPORTS_UNCACHED_ACCELERATED
>
> +config SYS_HAS_CPU_LOONGSON3
> +	bool
> +	select CPU_SUPPORTS_CPUFREQ
> +
>   config SYS_HAS_CPU_LOONGSON1B
>   	bool
>
> @@ -1703,7 +1720,7 @@ choice
>
>   config PAGE_SIZE_4KB
>   	bool "4kB"
> -	depends on !CPU_LOONGSON2
> +	depends on !CPU_LOONGSON2 && !CPU_LOONGSON3
>   	help
>   	 This option select the standard 4kB Linux page size.  On some
>   	 R3000-family processors this is the only available page size.  Using
> @@ -2373,6 +2390,16 @@ config PCI
>   	  your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
>   	  say Y, otherwise N.
>
> +config HT_PCI
> +	bool "Support for HT-linked PCI"
> +	depends on CPU_LOONGSON3
> +	select PCI_DOMAINS
> +	help
> +	  Loongson family machines use Hyper-Transport bus for inter-core
> +	  connection and device connection. The PCI bus is a subordinate
> +	  linked at HT. Choose Y unless you are using Loongson 2E/2F based
> +	  machines.
> +

Should this default to y, given that it is selected in the defconfig? 
Also, the comment referring to 2E/2F is redundant given that it depends 
on CPU_LOONGSON3 and cannot be selected on those machines.

>   config PCI_DOMAINS
>   	bool
>
> diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
> index 263beb9..4f3967c 100644
> --- a/arch/mips/loongson/Kconfig
> +++ b/arch/mips/loongson/Kconfig
> @@ -59,6 +59,33 @@ config LEMOTE_MACH2F
>
>   	  These family machines include fuloong2f mini PC, yeeloong2f notebook,
>   	  LingLoong allinone PC and so forth.
> +
> +config LEMOTE_MACH3A
> +	bool "Lemote Loongson 3A family machines"
> +	select ARCH_SPARSEMEM_ENABLE
> +	select GENERIC_ISA_DMA_SUPPORT_BROKEN
> +	select GENERIC_HARDIRQS_NO__DO_IRQ
> +	select BOOT_ELF32
> +	select BOARD_SCACHE
> +	select CSRC_R4K
> +	select CEVT_R4K
> +	select CPU_HAS_WB
> +	select HW_HAS_PCI
> +	select ISA
> +	select I8259
> +	select IRQ_CPU
> +	select SYS_HAS_CPU_LOONGSON3
> +	select SYS_HAS_EARLY_PRINTK
> +	select SYS_SUPPORTS_SMP
> +	select SYS_SUPPORTS_64BIT_KERNEL
> +	select SYS_SUPPORTS_HIGHMEM
> +	select SYS_SUPPORTS_LITTLE_ENDIAN
> +	select LOONGSON_MC146818
> +	select ZONE_DMA32 if 64BIT
> +	select LEFI_FIRMWARE_INTERFACE
> +	help
> +		Lemote Loongson 3A family machines utilize the 3A revision of
> +		Loongson processor and RS780/SBX00 chipset.
>   endchoice

Add "select NR_CPUS_DEFAULT_4" on here? Currently creating a 
configuration without using the loongson3_defconfig will default to 2, 
but unless I'm mistaken, all 3A machines are quad core?

>
>   config CS5536
> @@ -86,8 +114,24 @@ config LOONGSON_UART_BASE
>   	default y
>   	depends on EARLY_PRINTK || SERIAL_8250
>
> +config IOMMU_HELPER
> +	bool
> +
> +config NEED_SG_DMA_LENGTH
> +	bool
> +
> +config SWIOTLB
> +	bool "Soft IOMMU Support for Big Memory (>4GB)"
> +	depends on CPU_LOONGSON3
> +	select IOMMU_HELPER
> +	select NEED_SG_DMA_LENGTH
> +	select NEED_DMA_MAP_STATE
> +

Again, default to y?

Thanks,
Alex

>   config LOONGSON_MC146818
>   	bool
>   	default n
>
> +config LEFI_FIRMWARE_INTERFACE
> +	bool
> +
>   endif # MACH_LOONGSON
> diff --git a/arch/mips/loongson/Platform b/arch/mips/loongson/Platform
> index 29692e5..6205372 100644
> --- a/arch/mips/loongson/Platform
> +++ b/arch/mips/loongson/Platform
> @@ -30,3 +30,4 @@ platform-$(CONFIG_MACH_LOONGSON) += loongson/
>   cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely
>   load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000
>   load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000
> +load-$(CONFIG_CPU_LOONGSON3) += 0xffffffff80200000
>

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

* Re: [PATCH V16 10/12] MIPS: Loongson 3: Add Loongson-3 SMP support
@ 2014-01-09 13:19     ` Alex Smith
  0 siblings, 0 replies; 55+ messages in thread
From: Alex Smith @ 2014-01-09 13:19 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, Aurelien Jarno,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On 08/01/14 02:44, Huacai Chen wrote:
> IPI registers of Loongson-3 include IPI_SET, IPI_CLEAR, IPI_STATUS,
> IPI_EN and IPI_MAILBOX_BUF. Each bit of IPI_STATUS indicate a type of
> IPI and IPI_EN indicate whether the IPI is enabled. The sender write 1
> to IPI_SET bits generate IPIs in IPI_STATUS, and receiver write 1 to
> bits of IPI_CLEAR to clear IPIs. IPI_MAILBOX_BUF are used to deliver
> more information about IPIs.
>
> Why we change code in arch/mips/loongson/common/setup.c?
>
> If without this change, when SMP configured, system cannot boot since
> it hang at printk() in cgroup_init_early(). The root cause is:
>
> console_trylock()
>    \-->down_trylock(&console_sem)
>      \-->raw_spin_unlock_irqrestore(&sem->lock, flags)
>        \-->_raw_spin_unlock_irqrestore()(SMP/UP have different versions)
>          \-->__raw_spin_unlock_irqrestore()  (following is the SMP case)
>            \-->do_raw_spin_unlock()
>              \-->arch_spin_unlock()
>                \-->nudge_writes()
>                  \-->mb()
>                    \-->wbflush()
>                      \-->__wbflush()
>
> In previous code __wbflush() is initialized in plat_mem_setup(), but
> cgroup_init_early() is called before plat_mem_setup(). Therefore, In
> this patch we make changes to avoid boot failure.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>   arch/mips/include/asm/mach-loongson/irq.h      |    2 +
>   arch/mips/include/asm/mach-loongson/loongson.h |    1 +
>   arch/mips/loongson/common/init.c               |    3 +
>   arch/mips/loongson/common/setup.c              |    8 +-
>   arch/mips/loongson/loongson-3/Makefile         |    2 +
>   arch/mips/loongson/loongson-3/irq.c            |   20 ++
>   arch/mips/loongson/loongson-3/smp.c            |  279 ++++++++++++++++++++++++
>   arch/mips/loongson/loongson-3/smp.h            |   24 ++
>   8 files changed, 334 insertions(+), 5 deletions(-)
>   create mode 100644 arch/mips/loongson/loongson-3/smp.c
>   create mode 100644 arch/mips/loongson/loongson-3/smp.h
>
> diff --git a/arch/mips/include/asm/mach-loongson/irq.h b/arch/mips/include/asm/mach-loongson/irq.h
> index 5711e3b..d2f0e2a 100644
> --- a/arch/mips/include/asm/mach-loongson/irq.h
> +++ b/arch/mips/include/asm/mach-loongson/irq.h
> @@ -22,5 +22,7 @@
>
>   #endif
>
> +extern void loongson3_ipi_interrupt(struct pt_regs *regs);
> +
>   #include_next <irq.h>
>   #endif /* __ASM_MACH_LOONGSON_IRQ_H_ */
> diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
> index 69e9d9e..f185907 100644
> --- a/arch/mips/include/asm/mach-loongson/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson/loongson.h
> @@ -27,6 +27,7 @@ extern void mach_prepare_shutdown(void);
>   /* environment arguments from bootloader */
>   extern u32 cpu_clock_freq;
>   extern u32 memsize, highmemsize;
> +extern struct plat_smp_ops loongson3_smp_ops;
>
>   /* loongson-specific command line, env and memory initialization */
>   extern void __init prom_init_memory(void);
> diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
> index 81ba3b4..a7c521b 100644
> --- a/arch/mips/loongson/common/init.c
> +++ b/arch/mips/loongson/common/init.c
> @@ -33,6 +33,9 @@ void __init prom_init(void)
>
>   	/*init the uart base address */
>   	prom_init_uart_base();
> +#if defined(CONFIG_SMP)
> +	register_smp_ops(&loongson3_smp_ops);
> +#endif
>   }
>
>   void __init prom_free_prom_memory(void)
> diff --git a/arch/mips/loongson/common/setup.c b/arch/mips/loongson/common/setup.c
> index 8223f8a..bb4ac92 100644
> --- a/arch/mips/loongson/common/setup.c
> +++ b/arch/mips/loongson/common/setup.c
> @@ -18,9 +18,6 @@
>   #include <linux/screen_info.h>
>   #endif
>
> -void (*__wbflush)(void);
> -EXPORT_SYMBOL(__wbflush);
> -
>   static void wbflush_loongson(void)
>   {
>   	asm(".set\tpush\n\t"
> @@ -32,10 +29,11 @@ static void wbflush_loongson(void)
>   	    ".set mips0\n\t");
>   }
>
> +void (*__wbflush)(void) = wbflush_loongson;
> +EXPORT_SYMBOL(__wbflush);
> +
>   void __init plat_mem_setup(void)
>   {
> -	__wbflush = wbflush_loongson;
> -
>   #ifdef CONFIG_VT
>   #if defined(CONFIG_VGA_CONSOLE)
>   	conswitchp = &vga_con;
> diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
> index b9968cd..70152b2 100644
> --- a/arch/mips/loongson/loongson-3/Makefile
> +++ b/arch/mips/loongson/loongson-3/Makefile
> @@ -2,3 +2,5 @@
>   # Makefile for Loongson-3 family machines
>   #
>   obj-y			+= irq.o
> +
> +obj-$(CONFIG_SMP)	+= smp.o
> diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
> index 3b52d56..d8920a8 100644
> --- a/arch/mips/loongson/loongson-3/irq.c
> +++ b/arch/mips/loongson/loongson-3/irq.c
> @@ -40,6 +40,10 @@ void mach_irq_dispatch(unsigned int pending)
>   {
>   	if (pending & CAUSEF_IP7)
>   		do_IRQ(LOONGSON_TIMER_IRQ);
> +#if defined(CONFIG_SMP)
> +	else if (pending & CAUSEF_IP6)
> +		loongson3_ipi_interrupt(NULL);
> +#endif
>   	else if (pending & CAUSEF_IP3)
>   		ht_irqdispatch();
>   	else if (pending & CAUSEF_IP2)
> @@ -59,10 +63,26 @@ static inline void mask_loongson_irq(struct irq_data *d)
>   {
>   	clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
>   	irq_disable_hazard();
> +
> +	/* Workaround: UART IRQ may deliver to any core */
> +	if (d->irq == LOONGSON_UART_IRQ) {
> +		int cpu = smp_processor_id();
> +
> +		LOONGSON_INT_ROUTER_INTENCLR = 1 << 10;
> +		LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
> +	}
>   }
>
>   static inline void unmask_loongson_irq(struct irq_data *d)
>   {
> +	/* Workaround: UART IRQ may deliver to any core */
> +	if (d->irq == LOONGSON_UART_IRQ) {
> +		int cpu = smp_processor_id();
> +
> +		LOONGSON_INT_ROUTER_INTENSET = 1 << 10;
> +		LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
> +	}
> +
>   	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
>   	irq_enable_hazard();
>   }
> diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
> new file mode 100644
> index 0000000..a264bcb
> --- /dev/null
> +++ b/arch/mips/loongson/loongson-3/smp.c
> @@ -0,0 +1,279 @@
> +/*
> + * Copyright (C) 2010, 2011, 2012, Lemote, Inc.
> + * Author: Chen Huacai, chenhc@lemote.com
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
> + */

Don't need the FSF address again, as Aurelien said for patch 5.

> +
> +#include <linux/init.h>
> +#include <linux/cpu.h>
> +#include <linux/sched.h>
> +#include <linux/smp.h>
> +#include <linux/cpufreq.h>
> +#include <asm/processor.h>
> +#include <asm/time.h>
> +#include <asm/clock.h>
> +#include <asm/tlbflush.h>
> +#include <loongson.h>
> +
> +#include "smp.h"
> +
> +/* read a 64bit value from ipi register */
> +uint64_t loongson3_ipi_read64(void *addr)
> +{
> +	return readq(addr);
> +};
> +
> +/* write a 64bit value to ipi register */
> +void loongson3_ipi_write64(uint64_t action, void *addr)
> +{
> +	writeq(action, addr);
> +	__wbflush();
> +};
> +
> +/* read a 32bit value from ipi register */
> +uint32_t loongson3_ipi_read32(void *addr)
> +{
> +	return readl(addr);
> +};
> +
> +/* write a 32bit value to ipi register */
> +void loongson3_ipi_write32(uint32_t action, void *addr)
> +{
> +	writel(action, addr);
> +	__wbflush();
> +};

I don't see these used anywhere else outside this file, so add static. 
Also, remove the semicolons after the final brace on each function.

> +
> +static void *ipi_set0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + SET0),
> +};
> +
> +static void *ipi_clear0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + CLEAR0),
> +};
> +
> +static void *ipi_status0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + STATUS0),
> +};
> +
> +static void *ipi_en0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + EN0),
> +};
> +
> +static void *ipi_mailbox_buf[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group0_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group0_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group0_base + smp_core3_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core3_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core3_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core3_offset + BUF),
> +};
> +
> +/*
> + * Simple enough, just poke the appropriate ipi register
> + */
> +static void loongson3_send_ipi_single(int cpu, unsigned int action)
> +{
> +	loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu]);
> +}
> +
> +static void
> +loongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action)
> +{
> +	unsigned int i;
> +
> +	for_each_cpu(i, mask)
> +		loongson3_ipi_write32((u32)action, ipi_set0_regs[i]);
> +}
> +
> +void loongson3_ipi_interrupt(struct pt_regs *regs)
> +{
> +	int cpu = smp_processor_id();
> +	unsigned int action;
> +
> +	/* Load the ipi register to figure out what we're supposed to do */
> +	action = loongson3_ipi_read32(ipi_status0_regs[cpu]);
> +
> +	/* Clear the ipi register to clear the interrupt */
> +	loongson3_ipi_write32((u32)action, ipi_clear0_regs[cpu]);
> +
> +	if (action & SMP_RESCHEDULE_YOURSELF)
> +		scheduler_ipi();
> +
> +	if (action & SMP_CALL_FUNCTION)
> +		smp_call_function_interrupt();
> +}
> +
> +/*
> + * SMP init and finish on secondary CPUs
> + */
> +void loongson3_init_secondary(void)
> +{
> +	int i;
> +	unsigned int imask = STATUSF_IP7 | STATUSF_IP6 |
> +			     STATUSF_IP3 | STATUSF_IP2;
> +
> +	/* Set interrupt mask, but don't enable */
> +	change_c0_status(ST0_IM, imask);
> +
> +	for (i = 0; i < loongson_sysconf.nr_cpus; i++)
> +		loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]);
> +}
> +
> +void loongson3_smp_finish(void)
> +{
> +	write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
> +	local_irq_enable();
> +	loongson3_ipi_write64(0,
> +			(void *)(ipi_mailbox_buf[smp_processor_id()]+0x0));
> +	pr_info("CPU#%d finished, CP0_ST=%x\n",
> +			smp_processor_id(), read_c0_status());
> +}
> +
> +void __init loongson3_smp_setup(void)
> +{
> +	int i, num;
> +
> +	init_cpu_possible(cpu_none_mask);
> +	set_cpu_possible(0, true);
> +
> +	__cpu_number_map[0] = 0;
> +	__cpu_logical_map[0] = 0;
> +
> +	/* For unified kernel, NR_CPUS is the maximum possible value,
> +	 * loongson_sysconf.nr_cpus is the really present value */
> +	for (i = 1, num = 0; i < loongson_sysconf.nr_cpus; i++) {
> +		set_cpu_possible(i, true);
> +		__cpu_number_map[i] = ++num;
> +		__cpu_logical_map[num] = i;
> +	}
> +	pr_info("Detected %i available secondary CPU(s)\n", num);
> +}
> +
> +void __init loongson3_prepare_cpus(unsigned int max_cpus)
> +{
> +}
> +
> +/*
> + * Setup the PC, SP, and GP of a secondary processor and start it runing!
> + */
> +void loongson3_boot_secondary(int cpu, struct task_struct *idle)
> +{
> +	unsigned long startargs[4];
> +
> +	pr_info("Booting CPU#%d...\n", cpu);
> +
> +	/* startargs[] are initial PC, SP and GP for secondary CPU */
> +	startargs[0] = (unsigned long)&smp_bootstrap;
> +	startargs[1] = (unsigned long)__KSTK_TOS(idle);
> +	startargs[2] = (unsigned long)task_thread_info(idle);
> +	startargs[3] = 0;
> +
> +	pr_debug("CPU#%d, func_pc=%lx, sp=%lx, gp=%lx\n",
> +			cpu, startargs[0], startargs[1], startargs[2]);
> +
> +	loongson3_ipi_write64(startargs[3], (void *)(ipi_mailbox_buf[cpu]+0x18));
> +	loongson3_ipi_write64(startargs[2], (void *)(ipi_mailbox_buf[cpu]+0x10));
> +	loongson3_ipi_write64(startargs[1], (void *)(ipi_mailbox_buf[cpu]+0x8));
> +	loongson3_ipi_write64(startargs[0], (void *)(ipi_mailbox_buf[cpu]+0x0));
> +}
> +
> +/*
> + * Final cleanup after all secondaries booted
> + */
> +void __init loongson3_cpus_done(void)
> +{
> +}
> +
> +struct plat_smp_ops loongson3_smp_ops = {
> +	.send_ipi_single = loongson3_send_ipi_single,
> +	.send_ipi_mask = loongson3_send_ipi_mask,
> +	.init_secondary = loongson3_init_secondary,
> +	.smp_finish = loongson3_smp_finish,
> +	.cpus_done = loongson3_cpus_done,
> +	.boot_secondary = loongson3_boot_secondary,
> +	.smp_setup = loongson3_smp_setup,
> +	.prepare_cpus = loongson3_prepare_cpus,
> +};

Add static on all of the functions above referenced in 
loongson3_smp_ops, they aren't referenced outside this file.

> diff --git a/arch/mips/loongson/loongson-3/smp.h b/arch/mips/loongson/loongson-3/smp.h
> new file mode 100644
> index 0000000..dc9ce69
> --- /dev/null
> +++ b/arch/mips/loongson/loongson-3/smp.h
> @@ -0,0 +1,24 @@
> +/* for Loongson-3A smp support */
> +
> +/* 4 groups(nodes) in maximum in numa case */
> +#define  smp_core_group0_base    0x900000003ff01000
> +#define  smp_core_group1_base    0x900010003ff01000
> +#define  smp_core_group2_base    0x900020003ff01000
> +#define  smp_core_group3_base    0x900030003ff01000
> +
> +/* 4 cores in each group(node) */
> +#define  smp_core0_offset  0x000
> +#define  smp_core1_offset  0x100
> +#define  smp_core2_offset  0x200
> +#define  smp_core3_offset  0x300

Macros defining constants should have capitalized names.

> +
> +/* ipi registers offsets */
> +#define  STATUS0  0x00
> +#define  EN0      0x04
> +#define  SET0     0x08
> +#define  CLEAR0   0x0c
> +#define  STATUS1  0x10
> +#define  MASK1    0x14
> +#define  SET1     0x18
> +#define  CLEAR1   0x1c
> +#define  BUF      0x20
>

Even though it's only included from smp.c, headers should probably have 
include guard #ifdefs.

Thanks,
Alex

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

* Re: [PATCH V16 10/12] MIPS: Loongson 3: Add Loongson-3 SMP support
@ 2014-01-09 13:19     ` Alex Smith
  0 siblings, 0 replies; 55+ messages in thread
From: Alex Smith @ 2014-01-09 13:19 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, Aurelien Jarno,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On 08/01/14 02:44, Huacai Chen wrote:
> IPI registers of Loongson-3 include IPI_SET, IPI_CLEAR, IPI_STATUS,
> IPI_EN and IPI_MAILBOX_BUF. Each bit of IPI_STATUS indicate a type of
> IPI and IPI_EN indicate whether the IPI is enabled. The sender write 1
> to IPI_SET bits generate IPIs in IPI_STATUS, and receiver write 1 to
> bits of IPI_CLEAR to clear IPIs. IPI_MAILBOX_BUF are used to deliver
> more information about IPIs.
>
> Why we change code in arch/mips/loongson/common/setup.c?
>
> If without this change, when SMP configured, system cannot boot since
> it hang at printk() in cgroup_init_early(). The root cause is:
>
> console_trylock()
>    \-->down_trylock(&console_sem)
>      \-->raw_spin_unlock_irqrestore(&sem->lock, flags)
>        \-->_raw_spin_unlock_irqrestore()(SMP/UP have different versions)
>          \-->__raw_spin_unlock_irqrestore()  (following is the SMP case)
>            \-->do_raw_spin_unlock()
>              \-->arch_spin_unlock()
>                \-->nudge_writes()
>                  \-->mb()
>                    \-->wbflush()
>                      \-->__wbflush()
>
> In previous code __wbflush() is initialized in plat_mem_setup(), but
> cgroup_init_early() is called before plat_mem_setup(). Therefore, In
> this patch we make changes to avoid boot failure.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>   arch/mips/include/asm/mach-loongson/irq.h      |    2 +
>   arch/mips/include/asm/mach-loongson/loongson.h |    1 +
>   arch/mips/loongson/common/init.c               |    3 +
>   arch/mips/loongson/common/setup.c              |    8 +-
>   arch/mips/loongson/loongson-3/Makefile         |    2 +
>   arch/mips/loongson/loongson-3/irq.c            |   20 ++
>   arch/mips/loongson/loongson-3/smp.c            |  279 ++++++++++++++++++++++++
>   arch/mips/loongson/loongson-3/smp.h            |   24 ++
>   8 files changed, 334 insertions(+), 5 deletions(-)
>   create mode 100644 arch/mips/loongson/loongson-3/smp.c
>   create mode 100644 arch/mips/loongson/loongson-3/smp.h
>
> diff --git a/arch/mips/include/asm/mach-loongson/irq.h b/arch/mips/include/asm/mach-loongson/irq.h
> index 5711e3b..d2f0e2a 100644
> --- a/arch/mips/include/asm/mach-loongson/irq.h
> +++ b/arch/mips/include/asm/mach-loongson/irq.h
> @@ -22,5 +22,7 @@
>
>   #endif
>
> +extern void loongson3_ipi_interrupt(struct pt_regs *regs);
> +
>   #include_next <irq.h>
>   #endif /* __ASM_MACH_LOONGSON_IRQ_H_ */
> diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
> index 69e9d9e..f185907 100644
> --- a/arch/mips/include/asm/mach-loongson/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson/loongson.h
> @@ -27,6 +27,7 @@ extern void mach_prepare_shutdown(void);
>   /* environment arguments from bootloader */
>   extern u32 cpu_clock_freq;
>   extern u32 memsize, highmemsize;
> +extern struct plat_smp_ops loongson3_smp_ops;
>
>   /* loongson-specific command line, env and memory initialization */
>   extern void __init prom_init_memory(void);
> diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
> index 81ba3b4..a7c521b 100644
> --- a/arch/mips/loongson/common/init.c
> +++ b/arch/mips/loongson/common/init.c
> @@ -33,6 +33,9 @@ void __init prom_init(void)
>
>   	/*init the uart base address */
>   	prom_init_uart_base();
> +#if defined(CONFIG_SMP)
> +	register_smp_ops(&loongson3_smp_ops);
> +#endif
>   }
>
>   void __init prom_free_prom_memory(void)
> diff --git a/arch/mips/loongson/common/setup.c b/arch/mips/loongson/common/setup.c
> index 8223f8a..bb4ac92 100644
> --- a/arch/mips/loongson/common/setup.c
> +++ b/arch/mips/loongson/common/setup.c
> @@ -18,9 +18,6 @@
>   #include <linux/screen_info.h>
>   #endif
>
> -void (*__wbflush)(void);
> -EXPORT_SYMBOL(__wbflush);
> -
>   static void wbflush_loongson(void)
>   {
>   	asm(".set\tpush\n\t"
> @@ -32,10 +29,11 @@ static void wbflush_loongson(void)
>   	    ".set mips0\n\t");
>   }
>
> +void (*__wbflush)(void) = wbflush_loongson;
> +EXPORT_SYMBOL(__wbflush);
> +
>   void __init plat_mem_setup(void)
>   {
> -	__wbflush = wbflush_loongson;
> -
>   #ifdef CONFIG_VT
>   #if defined(CONFIG_VGA_CONSOLE)
>   	conswitchp = &vga_con;
> diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
> index b9968cd..70152b2 100644
> --- a/arch/mips/loongson/loongson-3/Makefile
> +++ b/arch/mips/loongson/loongson-3/Makefile
> @@ -2,3 +2,5 @@
>   # Makefile for Loongson-3 family machines
>   #
>   obj-y			+= irq.o
> +
> +obj-$(CONFIG_SMP)	+= smp.o
> diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
> index 3b52d56..d8920a8 100644
> --- a/arch/mips/loongson/loongson-3/irq.c
> +++ b/arch/mips/loongson/loongson-3/irq.c
> @@ -40,6 +40,10 @@ void mach_irq_dispatch(unsigned int pending)
>   {
>   	if (pending & CAUSEF_IP7)
>   		do_IRQ(LOONGSON_TIMER_IRQ);
> +#if defined(CONFIG_SMP)
> +	else if (pending & CAUSEF_IP6)
> +		loongson3_ipi_interrupt(NULL);
> +#endif
>   	else if (pending & CAUSEF_IP3)
>   		ht_irqdispatch();
>   	else if (pending & CAUSEF_IP2)
> @@ -59,10 +63,26 @@ static inline void mask_loongson_irq(struct irq_data *d)
>   {
>   	clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
>   	irq_disable_hazard();
> +
> +	/* Workaround: UART IRQ may deliver to any core */
> +	if (d->irq == LOONGSON_UART_IRQ) {
> +		int cpu = smp_processor_id();
> +
> +		LOONGSON_INT_ROUTER_INTENCLR = 1 << 10;
> +		LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
> +	}
>   }
>
>   static inline void unmask_loongson_irq(struct irq_data *d)
>   {
> +	/* Workaround: UART IRQ may deliver to any core */
> +	if (d->irq == LOONGSON_UART_IRQ) {
> +		int cpu = smp_processor_id();
> +
> +		LOONGSON_INT_ROUTER_INTENSET = 1 << 10;
> +		LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
> +	}
> +
>   	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
>   	irq_enable_hazard();
>   }
> diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
> new file mode 100644
> index 0000000..a264bcb
> --- /dev/null
> +++ b/arch/mips/loongson/loongson-3/smp.c
> @@ -0,0 +1,279 @@
> +/*
> + * Copyright (C) 2010, 2011, 2012, Lemote, Inc.
> + * Author: Chen Huacai, chenhc@lemote.com
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
> + */

Don't need the FSF address again, as Aurelien said for patch 5.

> +
> +#include <linux/init.h>
> +#include <linux/cpu.h>
> +#include <linux/sched.h>
> +#include <linux/smp.h>
> +#include <linux/cpufreq.h>
> +#include <asm/processor.h>
> +#include <asm/time.h>
> +#include <asm/clock.h>
> +#include <asm/tlbflush.h>
> +#include <loongson.h>
> +
> +#include "smp.h"
> +
> +/* read a 64bit value from ipi register */
> +uint64_t loongson3_ipi_read64(void *addr)
> +{
> +	return readq(addr);
> +};
> +
> +/* write a 64bit value to ipi register */
> +void loongson3_ipi_write64(uint64_t action, void *addr)
> +{
> +	writeq(action, addr);
> +	__wbflush();
> +};
> +
> +/* read a 32bit value from ipi register */
> +uint32_t loongson3_ipi_read32(void *addr)
> +{
> +	return readl(addr);
> +};
> +
> +/* write a 32bit value to ipi register */
> +void loongson3_ipi_write32(uint32_t action, void *addr)
> +{
> +	writel(action, addr);
> +	__wbflush();
> +};

I don't see these used anywhere else outside this file, so add static. 
Also, remove the semicolons after the final brace on each function.

> +
> +static void *ipi_set0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + SET0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + SET0),
> +};
> +
> +static void *ipi_clear0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + CLEAR0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + CLEAR0),
> +};
> +
> +static void *ipi_status0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + STATUS0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + STATUS0),
> +};
> +
> +static void *ipi_en0_regs[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group0_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group0_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group0_base + smp_core3_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group1_base + smp_core3_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group2_base + smp_core3_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core0_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core1_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core2_offset + EN0),
> +	(void *)(smp_core_group3_base + smp_core3_offset + EN0),
> +};
> +
> +static void *ipi_mailbox_buf[] = {
> +	(void *)(smp_core_group0_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group0_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group0_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group0_base + smp_core3_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group1_base + smp_core3_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group2_base + smp_core3_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core0_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core1_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core2_offset + BUF),
> +	(void *)(smp_core_group3_base + smp_core3_offset + BUF),
> +};
> +
> +/*
> + * Simple enough, just poke the appropriate ipi register
> + */
> +static void loongson3_send_ipi_single(int cpu, unsigned int action)
> +{
> +	loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu]);
> +}
> +
> +static void
> +loongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action)
> +{
> +	unsigned int i;
> +
> +	for_each_cpu(i, mask)
> +		loongson3_ipi_write32((u32)action, ipi_set0_regs[i]);
> +}
> +
> +void loongson3_ipi_interrupt(struct pt_regs *regs)
> +{
> +	int cpu = smp_processor_id();
> +	unsigned int action;
> +
> +	/* Load the ipi register to figure out what we're supposed to do */
> +	action = loongson3_ipi_read32(ipi_status0_regs[cpu]);
> +
> +	/* Clear the ipi register to clear the interrupt */
> +	loongson3_ipi_write32((u32)action, ipi_clear0_regs[cpu]);
> +
> +	if (action & SMP_RESCHEDULE_YOURSELF)
> +		scheduler_ipi();
> +
> +	if (action & SMP_CALL_FUNCTION)
> +		smp_call_function_interrupt();
> +}
> +
> +/*
> + * SMP init and finish on secondary CPUs
> + */
> +void loongson3_init_secondary(void)
> +{
> +	int i;
> +	unsigned int imask = STATUSF_IP7 | STATUSF_IP6 |
> +			     STATUSF_IP3 | STATUSF_IP2;
> +
> +	/* Set interrupt mask, but don't enable */
> +	change_c0_status(ST0_IM, imask);
> +
> +	for (i = 0; i < loongson_sysconf.nr_cpus; i++)
> +		loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]);
> +}
> +
> +void loongson3_smp_finish(void)
> +{
> +	write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
> +	local_irq_enable();
> +	loongson3_ipi_write64(0,
> +			(void *)(ipi_mailbox_buf[smp_processor_id()]+0x0));
> +	pr_info("CPU#%d finished, CP0_ST=%x\n",
> +			smp_processor_id(), read_c0_status());
> +}
> +
> +void __init loongson3_smp_setup(void)
> +{
> +	int i, num;
> +
> +	init_cpu_possible(cpu_none_mask);
> +	set_cpu_possible(0, true);
> +
> +	__cpu_number_map[0] = 0;
> +	__cpu_logical_map[0] = 0;
> +
> +	/* For unified kernel, NR_CPUS is the maximum possible value,
> +	 * loongson_sysconf.nr_cpus is the really present value */
> +	for (i = 1, num = 0; i < loongson_sysconf.nr_cpus; i++) {
> +		set_cpu_possible(i, true);
> +		__cpu_number_map[i] = ++num;
> +		__cpu_logical_map[num] = i;
> +	}
> +	pr_info("Detected %i available secondary CPU(s)\n", num);
> +}
> +
> +void __init loongson3_prepare_cpus(unsigned int max_cpus)
> +{
> +}
> +
> +/*
> + * Setup the PC, SP, and GP of a secondary processor and start it runing!
> + */
> +void loongson3_boot_secondary(int cpu, struct task_struct *idle)
> +{
> +	unsigned long startargs[4];
> +
> +	pr_info("Booting CPU#%d...\n", cpu);
> +
> +	/* startargs[] are initial PC, SP and GP for secondary CPU */
> +	startargs[0] = (unsigned long)&smp_bootstrap;
> +	startargs[1] = (unsigned long)__KSTK_TOS(idle);
> +	startargs[2] = (unsigned long)task_thread_info(idle);
> +	startargs[3] = 0;
> +
> +	pr_debug("CPU#%d, func_pc=%lx, sp=%lx, gp=%lx\n",
> +			cpu, startargs[0], startargs[1], startargs[2]);
> +
> +	loongson3_ipi_write64(startargs[3], (void *)(ipi_mailbox_buf[cpu]+0x18));
> +	loongson3_ipi_write64(startargs[2], (void *)(ipi_mailbox_buf[cpu]+0x10));
> +	loongson3_ipi_write64(startargs[1], (void *)(ipi_mailbox_buf[cpu]+0x8));
> +	loongson3_ipi_write64(startargs[0], (void *)(ipi_mailbox_buf[cpu]+0x0));
> +}
> +
> +/*
> + * Final cleanup after all secondaries booted
> + */
> +void __init loongson3_cpus_done(void)
> +{
> +}
> +
> +struct plat_smp_ops loongson3_smp_ops = {
> +	.send_ipi_single = loongson3_send_ipi_single,
> +	.send_ipi_mask = loongson3_send_ipi_mask,
> +	.init_secondary = loongson3_init_secondary,
> +	.smp_finish = loongson3_smp_finish,
> +	.cpus_done = loongson3_cpus_done,
> +	.boot_secondary = loongson3_boot_secondary,
> +	.smp_setup = loongson3_smp_setup,
> +	.prepare_cpus = loongson3_prepare_cpus,
> +};

Add static on all of the functions above referenced in 
loongson3_smp_ops, they aren't referenced outside this file.

> diff --git a/arch/mips/loongson/loongson-3/smp.h b/arch/mips/loongson/loongson-3/smp.h
> new file mode 100644
> index 0000000..dc9ce69
> --- /dev/null
> +++ b/arch/mips/loongson/loongson-3/smp.h
> @@ -0,0 +1,24 @@
> +/* for Loongson-3A smp support */
> +
> +/* 4 groups(nodes) in maximum in numa case */
> +#define  smp_core_group0_base    0x900000003ff01000
> +#define  smp_core_group1_base    0x900010003ff01000
> +#define  smp_core_group2_base    0x900020003ff01000
> +#define  smp_core_group3_base    0x900030003ff01000
> +
> +/* 4 cores in each group(node) */
> +#define  smp_core0_offset  0x000
> +#define  smp_core1_offset  0x100
> +#define  smp_core2_offset  0x200
> +#define  smp_core3_offset  0x300

Macros defining constants should have capitalized names.

> +
> +/* ipi registers offsets */
> +#define  STATUS0  0x00
> +#define  EN0      0x04
> +#define  SET0     0x08
> +#define  CLEAR0   0x0c
> +#define  STATUS1  0x10
> +#define  MASK1    0x14
> +#define  SET1     0x18
> +#define  CLEAR1   0x1c
> +#define  BUF      0x20
>

Even though it's only included from smp.c, headers should probably have 
include guard #ifdefs.

Thanks,
Alex

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

* Re: [PATCH V16 02/12] MIPS: Loongson: Add basic Loongson-3 CPU support
       [not found]     ` <CAAhV-H4tx=sCk=iUwuCfnCS+rbmtu5Y_UcpAn6JXDoobA+OGrQ@mail.gmail.com>
@ 2014-01-09 21:36       ` Aurelien Jarno
  2014-01-12  9:03         ` Huacai Chen
  0 siblings, 1 reply; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-09 21:36 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Thu, Jan 09, 2014 at 04:30:54PM +0800, Huacai Chen wrote:
> On Thu, Jan 9, 2014 at 3:58 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> 
> > On Wed, Jan 08, 2014 at 10:44:18AM +0800, Huacai Chen wrote:
> > > Basic Loongson-3 CPU support include CPU probing and TLB/cache
> > > initializing.
> > >
> > > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > > Signed-off-by: Hongliang Tao <taohl@lemote.com>
> > > Signed-off-by: Hua Yan <yanh@lemote.com>
> > > ---
> > >  arch/mips/include/asm/cpu-type.h |    4 ++
> > >  arch/mips/kernel/cpu-probe.c     |   14 ++++++--
> > >  arch/mips/mm/c-r4k.c             |   59
> > ++++++++++++++++++++++++++++++++++++++
> > >  arch/mips/mm/tlb-r4k.c           |    5 ++-
> > >  arch/mips/mm/tlbex.c             |    1 +
> > >  5 files changed, 77 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/arch/mips/include/asm/cpu-type.h
> > b/arch/mips/include/asm/cpu-type.h
> > > index 4a402cc..a591e63 100644
> > > --- a/arch/mips/include/asm/cpu-type.h
> > > +++ b/arch/mips/include/asm/cpu-type.h
> > > @@ -20,6 +20,10 @@ static inline int __pure __get_cpu_type(const int
> > cpu_type)
> > >       case CPU_LOONGSON2:
> > >  #endif
> > >
> > > +#ifdef CONFIG_SYS_HAS_CPU_LOONGSON3
> > > +     case CPU_LOONGSON3:
> > > +#endif
> > > +
> > >  #ifdef CONFIG_SYS_HAS_CPU_LOONGSON1B
> > >       case CPU_LOONGSON1:
> > >  #endif
> > > diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> > > index c814287..4bc81b2 100644
> > > --- a/arch/mips/kernel/cpu-probe.c
> > > +++ b/arch/mips/kernel/cpu-probe.c
> > > @@ -639,17 +639,23 @@ static inline void cpu_probe_legacy(struct
> > cpuinfo_mips *c, unsigned int cpu)
> > >                            MIPS_CPU_LLSC;
> > >               c->tlbsize = 64;
> > >               break;
> > > -     case PRID_IMP_LOONGSON2:
> > > -             c->cputype = CPU_LOONGSON2;
> > > -             __cpu_name[cpu] = "ICT Loongson-2";
> > > -
> > > +     case PRID_IMP_LOONGSON2: /* Loongson-2/3 have the same PRID_IMP
> > field */
> >
> > What about renaming that as something like PRID_IMP_LOONGSON23 given
> > it is for both Loongson 2 and 3?
> >
> Since Loongson-1 is 32-bit CPU and Loongson-2/3 are 64 bit, can I use
> PRID_IMP_LOONGSON_32 and PRID_IMP_LOONGSON_64?
> In my opinion these names are better.

That would be the best I agree.
 
> >
> > >               switch (c->processor_id & PRID_REV_MASK) {
> > >               case PRID_REV_LOONGSON2E:
> > > +                     c->cputype = CPU_LOONGSON2;
> > > +                     __cpu_name[cpu] = "ICT Loongson-2E";
> > >                       set_elf_platform(cpu, "loongson2e");
> > >                       break;
> > >               case PRID_REV_LOONGSON2F:
> > > +                     c->cputype = CPU_LOONGSON2;
> > > +                     __cpu_name[cpu] = "ICT Loongson-2F";
> > >                       set_elf_platform(cpu, "loongson2f");
> > >                       break;
> >
> > As remarked by Aaro Koskinen, changing the names of the Loongson 2 CPUs
> > (which is displayedd in /proc/cpuinfo) will break at least
> > GCC -march=native option. The name should be left unchanged.
> >
> Can I keep it as is and then submit a patch to GCC? I think it is important
> to distinguish 2E/2F/3A in cpuinfo.

I think first the patch has to be integrated to GCC, and then you have
to wait at least a few months so that people start using the new
version. Then it should be possible to modify this.

That said, other programs than GCC might use this information from
/proc/cpuinfo and might also break with this change.

> >
> > > +             case PRID_REV_LOONGSON3A:
> > > +                     c->cputype = CPU_LOONGSON3;
> > > +                     __cpu_name[cpu] = "ICT Loongson-3A";
> > > +                     set_elf_platform(cpu, "loongson3a");
> > > +                     break;
> > >               }
> > >
> > >               set_isa(c, MIPS_CPU_ISA_III);
> > > diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
> > > index 73f02da..cc02527 100644
> > > --- a/arch/mips/mm/c-r4k.c
> > > +++ b/arch/mips/mm/c-r4k.c
> > > @@ -348,6 +348,7 @@ static inline void local_r4k___flush_cache_all(void
> > * args)
> > >  {
> > >       switch (current_cpu_type()) {
> > >       case CPU_LOONGSON2:
> > > +     case CPU_LOONGSON3:
> > >       case CPU_R4000SC:
> > >       case CPU_R4000MC:
> > >       case CPU_R4400SC:
> > > @@ -1003,6 +1004,33 @@ static void probe_pcache(void)
> > >               c->dcache.waybit = 0;
> > >               break;
> > >
> > > +     case CPU_LOONGSON3:
> > > +             config1 = read_c0_config1();
> > > +             lsize = (config1 >> 19) & 7;
> > > +             if (lsize)
> > > +                     c->icache.linesz = 2 << lsize;
> > > +             else
> > > +                     c->icache.linesz = 0;
> >
> > Sorry to not have seen that before, but it can also be written as:
> >
> >         c->icache.linesz = lsize ? (2 << lsize) : 0;
> >
> > That said the current version is also fine, so as you prefer.
> >
> > > +             c->icache.sets = 64 << ((config1 >> 22) & 7);
> > > +             c->icache.ways = 1 + ((config1 >> 16) & 7);
> > > +             icache_size = c->icache.sets *
> > > +                                       c->icache.ways *
> > > +                                       c->icache.linesz;
> > > +             c->icache.waybit = 0;
> > > +
> > > +             lsize = (config1 >> 10) & 7;
> > > +             if (lsize)
> > > +                     c->dcache.linesz = 2 << lsize;
> > > +             else
> > > +                     c->dcache.linesz = 0;
> > > +             c->dcache.sets = 64 << ((config1 >> 13) & 7);
> > > +             c->dcache.ways = 1 + ((config1 >> 7) & 7);
> > > +             dcache_size = c->dcache.sets *
> > > +                                       c->dcache.ways *
> > > +                                       c->dcache.linesz;
> > > +             c->dcache.waybit = 0;
> > > +             break;
> > > +
> > >       default:
> > >               if (!(config & MIPS_CONF_M))
> > >                       panic("Don't know how to probe P-caches on this
> > cpu.");
> > > @@ -1222,6 +1250,33 @@ static void __init loongson2_sc_init(void)
> > >       c->options |= MIPS_CPU_INCLUSIVE_CACHES;
> > >  }
> > >
> > > +static void __init loongson3_sc_init(void)
> > > +{
> > > +     struct cpuinfo_mips *c = &current_cpu_data;
> > > +     unsigned int config2, lsize;
> > > +
> > > +     config2 = read_c0_config2();
> > > +     lsize = (config2 >> 4) & 15;
> > > +     if (lsize)
> > > +             c->scache.linesz = 2 << lsize;
> > > +     else
> > > +             c->scache.linesz = 0;
> > > +     c->scache.sets = 64 << ((config2 >> 8) & 15);
> > > +     c->scache.ways = 1 + (config2 & 15);
> > > +
> > > +     scache_size = c->scache.sets *
> > > +                               c->scache.ways *
> > > +                               c->scache.linesz;
> > > +     /* Loongson-3 has 4 cores, 1MB scache for each. scaches are shared
> > */
> > > +     scache_size *= 4;
> > > +     c->scache.waybit = 0;
> > > +     pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
> > > +            scache_size >> 10, way_string[c->scache.ways],
> > c->scache.linesz);
> > > +     if (scache_size)
> > > +             c->options |= MIPS_CPU_INCLUSIVE_CACHES;
> > > +     return;
> > > +}
> > > +
> > >  extern int r5k_sc_init(void);
> > >  extern int rm7k_sc_init(void);
> > >  extern int mips_sc_init(void);
> > > @@ -1274,6 +1329,10 @@ static void setup_scache(void)
> > >               loongson2_sc_init();
> > >               return;
> > >
> > > +     case CPU_LOONGSON3:
> > > +             loongson3_sc_init();
> > > +             return;
> > > +
> > >       case CPU_XLP:
> > >               /* don't need to worry about L2, fully coherent */
> > >               return;
> > > diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
> > > index da3b0b9..298f281 100644
> > > --- a/arch/mips/mm/tlb-r4k.c
> > > +++ b/arch/mips/mm/tlb-r4k.c
> > > @@ -53,13 +53,14 @@ extern void build_tlb_refill_handler(void);
> > >  #endif /* CONFIG_MIPS_MT_SMTC */
> > >
> > >  /*
> > > - * LOONGSON2 has a 4 entry itlb which is a subset of dtlb,
> > > - * unfortrunately, itlb is not totally transparent to software.
> > > + * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb,
> > > + * unfortunately, itlb is not totally transparent to software.
> > >   */
> > >  static inline void flush_itlb(void)
> > >  {
> > >       switch (current_cpu_type()) {
> > >       case CPU_LOONGSON2:
> > > +     case CPU_LOONGSON3:
> > >               write_c0_diag(4);
> > >               break;
> > >       default:
> > > diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
> > > index 183f2b5..f89124c 100644
> > > --- a/arch/mips/mm/tlbex.c
> > > +++ b/arch/mips/mm/tlbex.c
> > > @@ -579,6 +579,7 @@ static void build_tlb_write_entry(u32 **p, struct
> > uasm_label **l,
> > >       case CPU_BMIPS4380:
> > >       case CPU_BMIPS5000:
> > >       case CPU_LOONGSON2:
> > > +     case CPU_LOONGSON3:
> > >       case CPU_R5500:
> > >               if (m4kc_tlbp_war())
> > >                       uasm_i_nop(p);
> > > --
> > > 1.7.7.3
> > >
> > >
> >
> > --
> > Aurelien Jarno                          GPG: 1024D/F1BCDB73
> > aurelien@aurel32.net                 http://www.aurel32.net
> >
> >

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 04/12] MIPS: Loongson: Add UEFI-like firmware interface (LEFI) support
       [not found]     ` <CAAhV-H64BXsw5CBL-KW1eqXkYcadhHF2NeBH9YmWQz046Lpzzw@mail.gmail.com>
@ 2014-01-09 21:37       ` Aurelien Jarno
  0 siblings, 0 replies; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-09 21:37 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Thu, Jan 09, 2014 at 06:00:44PM +0800, Huacai Chen wrote:
> On Thu, Jan 9, 2014 at 6:58 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> 
> > On Wed, Jan 08, 2014 at 10:44:20AM +0800, Huacai Chen wrote:
> > > The new UEFI-like firmware interface (LEFI, i.e. Loongson Unified
> > > Firmware Interface) has 3 advantages:
> > >
> > > 1, Firmware export a physical memory map which is similar to X86's
> > >    E820 map, so prom_init_memory() will be more elegant that #ifdef
> > >    clauses can be removed.
> > > 2, Firmware export a pci irq routing table, we no longer need pci
> > >    irq routing fixup in kernel's code.
> > > 3, Firmware has a built-in vga bios, and its address is exported,
> > >    the linux kernel no longer need an embedded blob.
> > >
> > > With the LEFI interface, Loongson-3A/2G and all their successors can use
> > > a unified kernel. All Loongson-based machines support this new interface
> > > except 2E/2F series.
> > >
> > > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > > Signed-off-by: Hongliang Tao <taohl@lemote.com>
> > > Signed-off-by: Hua Yan <yanh@lemote.com>
> > > ---
> > >  arch/mips/include/asm/mach-loongson/boot_param.h |  159
> > ++++++++++++++++++++++
> > >  arch/mips/include/asm/mach-loongson/loongson.h   |    4 +-
> > >  arch/mips/loongson/common/env.c                  |   64 +++++++--
> > >  arch/mips/loongson/common/init.c                 |    9 +-
> > >  arch/mips/loongson/common/mem.c                  |   42 ++++++
> > >  arch/mips/loongson/common/pci.c                  |    6 +-
> > >  arch/mips/loongson/common/reset.c                |   21 +++
> > >  7 files changed, 285 insertions(+), 20 deletions(-)
> > >  create mode 100644 arch/mips/include/asm/mach-loongson/boot_param.h
> > >
> > > diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h
> > b/arch/mips/include/asm/mach-loongson/boot_param.h
> > > new file mode 100644
> > > index 0000000..234c0eb
> > > --- /dev/null
> > > +++ b/arch/mips/include/asm/mach-loongson/boot_param.h
> > > @@ -0,0 +1,159 @@
> > > +#ifndef __ASM_MACH_LOONGSON_BOOT_PARAM_H_
> > > +#define __ASM_MACH_LOONGSON_BOOT_PARAM_H_
> > > +
> > > +#define SYSTEM_RAM_LOW               1
> > > +#define SYSTEM_RAM_HIGH              2
> > > +#define MEM_RESERVED         3
> > > +#define PCI_IO                       4
> > > +#define PCI_MEM                      5
> > > +#define LOONGSON_CFG_REG     6
> > > +#define VIDEO_ROM            7
> > > +#define ADAPTER_ROM          8
> > > +#define ACPI_TABLE           9
> > > +#define MAX_MEMORY_TYPE              10
> > > +
> > > +#define LOONGSON3_BOOT_MEM_MAP_MAX 128
> > > +struct efi_memory_map_loongson {
> > > +     u16 vers;       /* version of efi_memory_map */
> > > +     u32 nr_map;     /* number of memory_maps */
> > > +     u32 mem_freq;   /* memory frequence */
> > > +     struct mem_map {
> > > +             u32 node_id;    /* node_id which memory attached to */
> > > +             u32 mem_type;   /* system memory, pci memory, pci io, etc.
> > */
> > > +             u64 mem_start;  /* memory map start address */
> > > +             u32 mem_size;   /* each memory_map size, not the total
> > size */
> > > +     } map[LOONGSON3_BOOT_MEM_MAP_MAX];
> > > +} __packed;
> > > +
> > > +enum loongson_cpu_type {
> > > +     Loongson_2E = 0,
> > > +     Loongson_2F = 1,
> > > +     Loongson_3A = 2,
> > > +     Loongson_3B = 3,
> > > +     Loongson_1A = 4,
> > > +     Loongson_1B = 5
> > > +};
> > > +
> > > +/*
> > > + * Capability and feature descriptor structure for MIPS CPU
> > > + */
> > > +struct efi_cpuinfo_loongson {
> > > +     u16 vers;     /* version of efi_cpuinfo_loongson */
> > > +     u32 processor_id; /* PRID, e.g. 6305, 6306 */
> > > +     u32 cputype;  /* Loongson_3A/3B, etc. */
> > > +     u32 total_node;   /* num of total numa nodes */
> > > +     u32 cpu_startup_core_id; /* Core id */
> > > +     u32 cpu_clock_freq; /* cpu_clock */
> > > +     u32 nr_cpus;
> > > +} __packed;
> > > +
> > > +struct system_loongson {
> > > +     u16 vers;     /* version of system_loongson */
> > > +     u32 ccnuma_smp; /* 0: no numa; 1: has numa */
> > > +     u32 sing_double_channel; /* 1:single; 2:double */
> > > +} __packed;
> > > +
> > > +struct irq_source_routing_table {
> > > +     u16 vers;
> > > +     u16 size;
> > > +     u16 rtr_bus;
> > > +     u16 rtr_devfn;
> > > +     u32 vendor;
> > > +     u32 device;
> > > +     u32 PIC_type;   /* conform use HT or PCI to route to CPU-PIC */
> > > +     u64 ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */
> > > +     u64 ht_enable;  /* irqs used in this PIC */
> > > +     u32 node_id;    /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */
> > > +     u64 pci_mem_start_addr;
> > > +     u64 pci_mem_end_addr;
> > > +     u64 pci_io_start_addr;
> > > +     u64 pci_io_end_addr;
> > > +     u64 pci_config_addr;
> > > +} __packed;
> > > +
> > > +struct interface_info {
> > > +     u16 vers; /* version of the specificition */
> > > +     u16 size;
> > > +     u8  flag;
> > > +     char description[64];
> > > +} __packed;
> > > +
> > > +#define MAX_RESOURCE_NUMBER 128
> > > +struct resource_loongson {
> > > +     u64 start; /* resource start address */
> > > +     u64 end;   /* resource end address */
> > > +     char name[64];
> > > +     u32 flags;
> > > +};
> > > +
> > > +struct archdev_data {};  /* arch specific additions */
> > > +
> > > +struct board_devices {
> > > +     char name[64];    /* hold the device name */
> > > +     u32 num_resources; /* number of device_resource */
> > > +     /* for each device's resource */
> > > +     struct resource_loongson resource[MAX_RESOURCE_NUMBER];
> > > +     /* arch specific additions */
> > > +     struct archdev_data archdata;
> > > +};
> > > +
> > > +struct loongson_special_attribute {
> > > +     u16 vers;     /* version of this special */
> > > +     char special_name[64]; /* special_atribute_name */
> > > +     u32 loongson_special_type; /* type of special device */
> > > +     /* for each device's resource */
> > > +     struct resource_loongson resource[MAX_RESOURCE_NUMBER];
> > > +};
> > > +
> > > +struct loongson_params {
> > > +     u64 memory_offset;      /* efi_memory_map_loongson struct offset */
> > > +     u64 cpu_offset;         /* efi_cpuinfo_loongson struct offset */
> > > +     u64 system_offset;      /* system_loongson struct offset */
> > > +     u64 irq_offset;         /* irq_source_routing_table struct offset
> > */
> > > +     u64 interface_offset;   /* interface_info struct offset */
> > > +     u64 special_offset;     /* loongson_special_attribute struct
> > offset */
> > > +     u64 boarddev_table_offset;  /* board_devices offset */
> > > +};
> > > +
> > > +struct smbios_tables {
> > > +     u16 vers;     /* version of smbios */
> > > +     u64 vga_bios; /* vga_bios address */
> > > +     struct loongson_params lp;
> > > +};
> > > +
> > > +struct efi_reset_system_t {
> > > +     u64 ResetCold;
> > > +     u64 ResetWarm;
> > > +     u64 ResetType;
> > > +     u64 Shutdown;
> > > +};
> > > +
> > > +struct efi_loongson {
> > > +     u64 mps;        /* MPS table */
> > > +     u64 acpi;       /* ACPI table (IA64 ext 0.71) */
> > > +     u64 acpi20;     /* ACPI table (ACPI 2.0) */
> > > +     struct smbios_tables smbios;    /* SM BIOS table */
> > > +     u64 sal_systab; /* SAL system table */
> > > +     u64 boot_info;  /* boot info table */
> > > +};
> > > +
> > > +struct boot_params {
> > > +     struct efi_loongson efi;
> > > +     struct efi_reset_system_t reset_system;
> > > +};
> > > +
> > > +struct loongson_system_configuration {
> > > +     u32 nr_cpus;
> > > +     enum loongson_cpu_type cputype;
> > > +     u64 ht_control_base;
> > > +     u64 pci_mem_start_addr;
> > > +     u64 pci_mem_end_addr;
> > > +     u64 pci_io_base;
> > > +     u64 restart_addr;
> > > +     u64 poweroff_addr;
> > > +     u64 vgabios_addr;
> > > +};
> > > +
> > > +extern struct efi_memory_map_loongson *emap;
> > > +extern struct loongson_system_configuration loongson_sysconf;
> >
> > Thanks a lot for the loongson_sysconf struct, it looks a lot more clean
> > now. What about emap? Isn't there any risk that the kernel reuse the
> > corresponding memory and that its content is lost? It should be possible
> > to hold a copy of this struct in loongson_sysconf.
> >
> > emap is only used at system init, won't be used at runtime.

Then you can probably move the emap pointer in the loongson_sysconf
struct.

> >
> > > +#endif
> > > diff --git a/arch/mips/include/asm/mach-loongson/loongson.h
> > b/arch/mips/include/asm/mach-loongson/loongson.h
> > > index b286534..5913ea0 100644
> > > --- a/arch/mips/include/asm/mach-loongson/loongson.h
> > > +++ b/arch/mips/include/asm/mach-loongson/loongson.h
> > > @@ -24,8 +24,8 @@ extern void mach_prepare_reboot(void);
> > >  extern void mach_prepare_shutdown(void);
> > >
> > >  /* environment arguments from bootloader */
> > > -extern unsigned long cpu_clock_freq;
> > > -extern unsigned long memsize, highmemsize;
> > > +extern u32 cpu_clock_freq;
> > > +extern u32 memsize, highmemsize;
> > >
> > >  /* loongson-specific command line, env and memory initialization */
> > >  extern void __init prom_init_memory(void);
> > > diff --git a/arch/mips/loongson/common/env.c
> > b/arch/mips/loongson/common/env.c
> > > index 0a18fcf..ba2b6df 100644
> > > --- a/arch/mips/loongson/common/env.c
> > > +++ b/arch/mips/loongson/common/env.c
> > > @@ -18,29 +18,37 @@
> > >   * option) any later version.
> > >   */
> > >  #include <linux/module.h>
> > > -
> > >  #include <asm/bootinfo.h>
> > > -
> > >  #include <loongson.h>
> > > +#include <boot_param.h>
> > > +
> > > +struct boot_params *boot_p;
> > > +struct loongson_params *loongson_p;
> > > +
> > > +struct efi_cpuinfo_loongson *ecpu;
> > > +struct efi_memory_map_loongson *emap;
> > > +struct system_loongson *esys;
> > > +struct irq_source_routing_table *eirq_source;
> > > +struct loongson_system_configuration loongson_sysconf;
> > >
> > > -unsigned long cpu_clock_freq;
> > > +u32 cpu_clock_freq;
> > >  EXPORT_SYMBOL(cpu_clock_freq);
> > > -unsigned long memsize, highmemsize;
> > >
> > >  #define parse_even_earlier(res, option, p)                           \
> > >  do {                                                                 \
> > >       unsigned int tmp __maybe_unused;                                \
> > >                                                                       \
> > >       if (strncmp(option, (char *)p, strlen(option)) == 0)            \
> > > -             tmp = strict_strtol((char *)p + strlen(option"="), 10,
> > &res); \
> > > +             tmp = kstrtou32((char *)p + strlen(option"="), 10, &res); \
> > >  } while (0)
> > >
> > >  void __init prom_init_env(void)
> > >  {
> > >       /* pmon passes arguments in 32bit pointers */
> > > -     int *_prom_envp;
> > > -     unsigned long bus_clock;
> > >       unsigned int processor_id;
> > > +
> > > +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
> > > +     int *_prom_envp;
> > >       long l;
> > >
> > >       /* firmware arguments are initialized in head.S */
> > > @@ -48,7 +56,6 @@ void __init prom_init_env(void)
> > >
> > >       l = (long)*_prom_envp;
> > >       while (l != 0) {
> > > -             parse_even_earlier(bus_clock, "busclock", l);
> > >               parse_even_earlier(cpu_clock_freq, "cpuclock", l);
> > >               parse_even_earlier(memsize, "memsize", l);
> > >               parse_even_earlier(highmemsize, "highmemsize", l);
> > > @@ -57,8 +64,38 @@ void __init prom_init_env(void)
> > >       }
> > >       if (memsize == 0)
> > >               memsize = 256;
> > > -     if (bus_clock == 0)
> > > -             bus_clock = 66000000;
> > > +     pr_info("memsize=%ld, highmemsize=%ld\n", memsize, highmemsize);
> > > +#else
> > > +     /* firmware arguments are initialized in head.S */
> > > +     boot_p = (struct boot_params *)fw_arg2;
> > > +     loongson_p = &(boot_p->efi.smbios.lp);
> > > +
> > > +     ecpu = (struct efi_cpuinfo_loongson *)
> > > +             ((u64)loongson_p + loongson_p->cpu_offset);
> > > +     emap = (struct efi_memory_map_loongson *)
> > > +             ((u64)loongson_p + loongson_p->memory_offset);
> > > +     eirq_source = (struct irq_source_routing_table *)
> > > +             ((u64)loongson_p + loongson_p->irq_offset);
> > > +
> > > +     cpu_clock_freq = ecpu->cpu_clock_freq;
> > > +     loongson_sysconf.cputype = ecpu->cputype;
> > > +     loongson_sysconf.nr_cpus = ecpu->nr_cpus;
> > > +     if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
> > > +             loongson_sysconf.nr_cpus = NR_CPUS;
> > > +
> > > +     loongson_sysconf.pci_mem_start_addr =
> > eirq_source->pci_mem_start_addr;
> > > +     loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
> > > +     loongson_sysconf.pci_io_base = eirq_source->pci_io_start_addr;
> > > +
> > > +     loongson_sysconf.restart_addr = boot_p->reset_system.ResetWarm;
> > > +     loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
> > > +
> > > +     loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
> > > +     loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios;
> > > +     pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr:
> > %llx\n",
> > > +             loongson_sysconf.poweroff_addr,
> > loongson_sysconf.restart_addr,
> > > +             loongson_sysconf.vgabios_addr);
> > > +#endif
> > >       if (cpu_clock_freq == 0) {
> > >               processor_id = (&current_cpu_data)->processor_id;
> > >               switch (processor_id & PRID_REV_MASK) {
> > > @@ -68,12 +105,13 @@ void __init prom_init_env(void)
> > >               case PRID_REV_LOONGSON2F:
> > >                       cpu_clock_freq = 797000000;
> > >                       break;
> > > +             case PRID_REV_LOONGSON3A:
> > > +                     cpu_clock_freq = 900000000;
> > > +                     break;
> > >               default:
> > >                       cpu_clock_freq = 100000000;
> > >                       break;
> > >               }
> > >       }
> > > -
> > > -     pr_info("busclock=%ld, cpuclock=%ld, memsize=%ld,
> > highmemsize=%ld\n",
> > > -             bus_clock, cpu_clock_freq, memsize, highmemsize);
> > > +     pr_info("CpuClock = %u\n", cpu_clock_freq);
> > >  }
> > > diff --git a/arch/mips/loongson/common/init.c
> > b/arch/mips/loongson/common/init.c
> > > index ae7af1f..81ba3b4 100644
> > > --- a/arch/mips/loongson/common/init.c
> > > +++ b/arch/mips/loongson/common/init.c
> > > @@ -17,10 +17,6 @@ unsigned long __maybe_unused
> > _loongson_addrwincfg_base;
> > >
> > >  void __init prom_init(void)
> > >  {
> > > -     /* init base address of io space */
> > > -     set_io_port_base((unsigned long)
> > > -             ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
> > > -
> > >  #ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
> > >       _loongson_addrwincfg_base = (unsigned long)
> > >               ioremap(LOONGSON_ADDRWINCFG_BASE,
> > LOONGSON_ADDRWINCFG_SIZE);
> > > @@ -28,6 +24,11 @@ void __init prom_init(void)
> > >
> > >       prom_init_cmdline();
> > >       prom_init_env();
> > > +
> > > +     /* init base address of io space */
> > > +     set_io_port_base((unsigned long)
> > > +             ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
> > > +
> > >       prom_init_memory();
> > >
> > >       /*init the uart base address */
> > > diff --git a/arch/mips/loongson/common/mem.c
> > b/arch/mips/loongson/common/mem.c
> > > index 8626a42..42b2431 100644
> > > --- a/arch/mips/loongson/common/mem.c
> > > +++ b/arch/mips/loongson/common/mem.c
> > > @@ -11,9 +11,14 @@
> > >  #include <asm/bootinfo.h>
> > >
> > >  #include <loongson.h>
> > > +#include <boot_param.h>
> > >  #include <mem.h>
> > >  #include <pci.h>
> > >
> > > +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
> > > +
> > > +u32 memsize, highmemsize;
> > > +
> > >  void __init prom_init_memory(void)
> > >  {
> > >       add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
> > > @@ -49,6 +54,43 @@ void __init prom_init_memory(void)
> > >  #endif /* !CONFIG_64BIT */
> > >  }
> > >
> > > +#else /* CONFIG_LEFI_FIRMWARE_INTERFACE */
> > > +
> > > +void __init prom_init_memory(void)
> > > +{
> > > +     int i;
> > > +     u32 node_id;
> > > +     u32 mem_type;
> > > +
> > > +     /* parse memory information */
> > > +     for (i = 0; i < emap->nr_map; i++) {
> > > +             node_id = emap->map[i].node_id;
> > > +             mem_type = emap->map[i].mem_type;
> > > +
> > > +             if (node_id == 0) {
> > > +                     switch (mem_type) {
> > > +                     case SYSTEM_RAM_LOW:
> > > +                             add_memory_region(emap->map[i].mem_start,
> > > +                                     (u64)emap->map[i].mem_size << 20,
> > > +                                     BOOT_MEM_RAM);
> > > +                             break;
> > > +                     case SYSTEM_RAM_HIGH:
> > > +                             add_memory_region(emap->map[i].mem_start,
> > > +                                     (u64)emap->map[i].mem_size << 20,
> > > +                                     BOOT_MEM_RAM);
> > > +                             break;
> > > +                     case MEM_RESERVED:
> > > +                             add_memory_region(emap->map[i].mem_start,
> > > +                                     (u64)emap->map[i].mem_size << 20,
> > > +                                     BOOT_MEM_RESERVED);
> > > +                             break;
> > > +                     }
> > > +             }
> > > +     }
> > > +}
> > > +
> > > +#endif /* CONFIG_LEFI_FIRMWARE_INTERFACE */
> > > +
> > >  /* override of arch/mips/mm/cache.c: __uncached_access */
> > >  int __uncached_access(struct file *file, unsigned long addr)
> > >  {
> > > diff --git a/arch/mips/loongson/common/pci.c
> > b/arch/mips/loongson/common/pci.c
> > > index fa77844..003ab4e 100644
> > > --- a/arch/mips/loongson/common/pci.c
> > > +++ b/arch/mips/loongson/common/pci.c
> > > @@ -11,6 +11,7 @@
> > >
> > >  #include <pci.h>
> > >  #include <loongson.h>
> > > +#include <boot_param.h>
> > >
> > >  static struct resource loongson_pci_mem_resource = {
> > >       .name   = "pci memory space",
> > > @@ -82,7 +83,10 @@ static int __init pcibios_init(void)
> > >       setup_pcimap();
> > >
> > >       loongson_pci_controller.io_map_base = mips_io_port_base;
> > > -
> > > +#ifdef CONFIG_LEFI_FIRMWARE_INTERFACE
> > > +     loongson_pci_mem_resource.start =
> > loongson_sysconf.pci_mem_start_addr;
> > > +     loongson_pci_mem_resource.end = loongson_sysconf.pci_mem_end_addr;
> > > +#endif
> > >       register_pci_controller(&loongson_pci_controller);
> > >
> > >       return 0;
> > > diff --git a/arch/mips/loongson/common/reset.c
> > b/arch/mips/loongson/common/reset.c
> > > index 65bfbb5..a60715e 100644
> > > --- a/arch/mips/loongson/common/reset.c
> > > +++ b/arch/mips/loongson/common/reset.c
> > > @@ -16,6 +16,7 @@
> > >  #include <asm/reboot.h>
> > >
> > >  #include <loongson.h>
> > > +#include <boot_param.h>
> > >
> > >  static inline void loongson_reboot(void)
> > >  {
> > > @@ -37,17 +38,37 @@ static inline void loongson_reboot(void)
> > >
> > >  static void loongson_restart(char *command)
> > >  {
> > > +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
> > >       /* do preparation for reboot */
> > >       mach_prepare_reboot();
> > >
> > >       /* reboot via jumping to boot base address */
> > >       loongson_reboot();
> > > +#else
> > > +     void (*fw_restart)(void) = (void *)loongson_sysconf.restart_addr;
> > > +
> > > +     fw_restart();
> > > +     while (1) {
> > > +             if (cpu_wait)
> > > +                     cpu_wait();
> > > +     }
> > > +#endif
> > >  }
> > >
> > >  static void loongson_poweroff(void)
> > >  {
> > > +#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
> > >       mach_prepare_shutdown();
> > >       unreachable();
> > > +#else
> > > +     void (*fw_poweroff)(void) = (void *)loongson_sysconf.poweroff_addr;
> > > +
> > > +     fw_poweroff();
> > > +     while (1) {
> > > +             if (cpu_wait)
> > > +                     cpu_wait();
> > > +     }
> > > +#endif
> > >  }
> > >
> > >  static void loongson_halt(void)
> > > --
> > > 1.7.7.3
> > >
> > >
> >
> > --
> > Aurelien Jarno                          GPG: 1024D/F1BCDB73
> > aurelien@aurel32.net                 http://www.aurel32.net
> >
> >

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 05/12] MIPS: Loongson 3: Add HT-linked PCI support
       [not found]     ` <CAAhV-H57tDmYByjVwhf3teFZkGowR4E9+OO1vO0kP3iAKTNJVw@mail.gmail.com>
@ 2014-01-09 21:38       ` Aurelien Jarno
  0 siblings, 0 replies; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-09 21:38 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Thu, Jan 09, 2014 at 06:25:02PM +0800, Huacai Chen wrote:
> On Thu, Jan 9, 2014 at 6:58 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> 
> > On Wed, Jan 08, 2014 at 10:44:21AM +0800, Huacai Chen wrote:
> > > Loongson family machines use Hyper-Transport bus for inter-core
> > > connection and device connection. The PCI bus is a subordinate
> > > linked at HT1.
> > >
> > > With LEFI firmware interface, We don't need fixup for PCI irq routing
> > > (except providing a VBIOS of the integrated GPU).
> > >
> > > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > > Signed-off-by: Hongliang Tao <taohl@lemote.com>
> > > Signed-off-by: Hua Yan <yanh@lemote.com>
> > > ---
> > >  arch/mips/include/asm/mach-loongson/loongson.h |    7 ++
> > >  arch/mips/include/asm/mach-loongson/pci.h      |    5 +
> > >  arch/mips/pci/Makefile                         |    1 +
> > >  arch/mips/pci/fixup-loongson3.c                |   70 ++++++++++++++++
> > >  arch/mips/pci/ops-loongson3.c                  |  101
> > ++++++++++++++++++++++++
> > >  5 files changed, 184 insertions(+), 0 deletions(-)
> > >  create mode 100644 arch/mips/pci/fixup-loongson3.c
> > >  create mode 100644 arch/mips/pci/ops-loongson3.c
> > >
> > > diff --git a/arch/mips/include/asm/mach-loongson/loongson.h
> > b/arch/mips/include/asm/mach-loongson/loongson.h
> > > index 5913ea0..f0367ff 100644
> > > --- a/arch/mips/include/asm/mach-loongson/loongson.h
> > > +++ b/arch/mips/include/asm/mach-loongson/loongson.h
> > > @@ -15,6 +15,7 @@
> > >  #include <linux/init.h>
> > >  #include <linux/irq.h>
> > >  #include <linux/kconfig.h>
> > > +#include <boot_param.h>
> > >
> > >  /* loongson internal northbridge initialization */
> > >  extern void bonito_irq_init(void);
> > > @@ -101,7 +102,13 @@ static inline void do_perfcnt_IRQ(void)
> > >  #define LOONGSON_PCICFG_BASE 0x1fe80000
> > >  #define LOONGSON_PCICFG_SIZE 0x00000800      /* 2K */
> > >  #define LOONGSON_PCICFG_TOP
> >  (LOONGSON_PCICFG_BASE+LOONGSON_PCICFG_SIZE-1)
> > > +
> > > +#if defined(CONFIG_HT_PCI)
> > > +#define LOONGSON_PCIIO_BASE  loongson_sysconf.pci_io_base
> > > +#else
> > >  #define LOONGSON_PCIIO_BASE  0x1fd00000
> >
> > If CONFIG_HT_PCI, it will use address 0x1fd00000. Does it have a chance
> > to work on Loongson 3?
> >
> > > +#endif
> > > +
> > >  #define LOONGSON_PCIIO_SIZE  0x00100000      /* 1M */
> > >  #define LOONGSON_PCIIO_TOP   (LOONGSON_PCIIO_BASE+LOONGSON_PCIIO_SIZE-1)
> > >
> > > diff --git a/arch/mips/include/asm/mach-loongson/pci.h
> > b/arch/mips/include/asm/mach-loongson/pci.h
> > > index bc99dab..1212774 100644
> > > --- a/arch/mips/include/asm/mach-loongson/pci.h
> > > +++ b/arch/mips/include/asm/mach-loongson/pci.h
> > > @@ -40,8 +40,13 @@ extern struct pci_ops loongson_pci_ops;
> > >  #else        /* loongson2f/32bit & loongson2e */
> > >
> > >  /* this pci memory space is mapped by pcimap in pci.c */
> > > +#ifdef CONFIG_CPU_LOONGSON3
> > > +#define LOONGSON_PCI_MEM_START       0x40000000UL
> > > +#define LOONGSON_PCI_MEM_END 0x7effffffUL
> > > +#else
> > >  #define LOONGSON_PCI_MEM_START       LOONGSON_PCILO1_BASE
> > >  #define LOONGSON_PCI_MEM_END (LOONGSON_PCILO1_BASE + 0x04000000 * 2)
> > > +#endif
> > >  /* this is an offset from mips_io_port_base */
> > >  #define LOONGSON_PCI_IO_START        0x00004000UL
> > >
> > > diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
> > > index 719e455..5475859 100644
> > > --- a/arch/mips/pci/Makefile
> > > +++ b/arch/mips/pci/Makefile
> > > @@ -29,6 +29,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_LEMOTE_MACH3A)  += fixup-loongson3.o ops-loongson3.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/fixup-loongson3.c
> > b/arch/mips/pci/fixup-loongson3.c
> > > new file mode 100644
> > > index 0000000..4a8477d
> > > --- /dev/null
> > > +++ b/arch/mips/pci/fixup-loongson3.c
> > > @@ -0,0 +1,70 @@
> > > +/*
> > > + * fixup-loongson3.c
> > > + *
> > > + * Copyright (C) 2012 Lemote, Inc.
> > > + * Author: Xiang Yu, xiangy@lemote.com
> > > + *         Chen Huacai, chenhc@lemote.com
> > > + *
> > > + * This program is free software; you can redistribute  it and/or
> > modify it
> > > + * under  the terms of  the GNU General  Public License as published by
> > the
> > > + * Free Software Foundation;  either version 2 of the  License, or (at
> > your
> > > + * option) any later version.
> > > + *
> > > + * THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR
> > IMPLIED
> > > + * WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED
> > WARRANTIES OF
> > > + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> >  IN
> > > + * NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT,
> > INDIRECT,
> > > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
> > BUT
> > > + * NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES;
> > LOSS OF
> > > + * USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED
> > AND ON
> > > + * ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR
> > TORT
> > > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> > USE OF
> > > + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> > > + *
> > > + * You should have received a copy of the  GNU General Public License
> > along
> > > + * with this program; if not, write  to the Free Software Foundation,
> > Inc.,
> > > + * 675 Mass Ave, Cambridge, MA 02139, USA.
> >
> > checkpatch.pl reports that the address is wrong, and it is correct. As
> > suggested the best option is to just remove the three lines above.
> >
> > > + *
> > > + */
> > > +
> > > +#include <linux/pci.h>
> > > +#include <boot_param.h>
> > > +
> > > +static void print_fixup_info(const struct pci_dev *pdev)
> > > +{
> > > +     dev_info(&pdev->dev, "Device %x:%x, irq %d\n",
> > > +                     pdev->vendor, pdev->device, pdev->irq);
> > > +}
> > > +
> > > +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> > > +{
> > > +     print_fixup_info(dev);
> > > +     return dev->irq;
> > > +}
> > > +
> > > +static void pci_fixup_radeon(struct pci_dev *pdev)
> > > +{
> > > +     if (pdev->resource[PCI_ROM_RESOURCE].start)
> > > +             return;
> > > +
> > > +     if (!loongson_sysconf.vgabios_addr)
> > > +             return;
> > > +
> > > +     pdev->resource[PCI_ROM_RESOURCE].start =
> > > +             loongson_sysconf.vgabios_addr;
> > > +     pdev->resource[PCI_ROM_RESOURCE].end   =
> > > +             loongson_sysconf.vgabios_addr + 256*1024 - 1;
> > > +     pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_COPY;
> > > +
> > > +     dev_info(&pdev->dev, "BAR %d: assigned %pR for Radeon ROM\n",
> > > +                     PCI_ROM_RESOURCE,
> > &pdev->resource[PCI_ROM_RESOURCE]);
> > > +}
> > > +
> > > +DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
> > > +                             PCI_CLASS_DISPLAY_VGA, 8,
> > pci_fixup_radeon);
> > > +
> > > +/* Do platform specific device initialization at pci_enable_device()
> > time */
> > > +int pcibios_plat_dev_init(struct pci_dev *dev)
> > > +{
> > > +     return 0;
> > > +}
> > > diff --git a/arch/mips/pci/ops-loongson3.c
> > b/arch/mips/pci/ops-loongson3.c
> > > new file mode 100644
> > > index 0000000..077eafa
> > > --- /dev/null
> > > +++ b/arch/mips/pci/ops-loongson3.c
> > > @@ -0,0 +1,101 @@
> > > +#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
> > > +
> > > +static int loongson3_pci_config_access(unsigned char access_type,
> > > +             struct pci_bus *bus, unsigned int devfn,
> > > +             int where, u32 *data)
> > > +{
> > > +     unsigned char busnum = bus->number;
> > > +     u_int64_t addr, type;
> > > +     void *addrp;
> > > +     int device = PCI_SLOT(devfn);
> > > +     int function = PCI_FUNC(devfn);
> > > +     int reg = where & ~3;
> > > +
> > > +     addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
> > > +     if (busnum == 0) {
> > > +             if (device > 31)
> > > +                     return PCIBIOS_DEVICE_NOT_FOUND;
> > > +             addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE) | (addr &
> > 0xffff));
> > > +             type = 0;
> > > +
> > > +     } else {
> > > +             addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE_TP1) | (addr));
> > > +             type = 0x10000;
> > > +     }
> > > +
> > > +     if (access_type == PCI_ACCESS_WRITE)
> > > +             writel(cpu_to_le32(*data), addrp);
> >
> > writel already includes the call to cpu_to_le32, so it can be written
> > directly as:
> >
> >         writel(*data) addrp);
> >
> > As cpu_to_le32 is a no-op on little endian, both work, but it is not
> > correct to use cpu_to_le32 here.
> >
> > > +     else {
> > > +             *data = le32_to_cpu(readl(addrp));
> >
> >
> > Same here, this should be written as :
> >
> >         *data = readl(addrp);
> >
> But why arch/mips/pci/ops-loongson2.c and arch/mips/pci/ops-bonito64.c use
> le32_to_cpu(readl(addrp)) and writel(cpu_to_le32(*data), addrp)?
> Maybe they are wrong?

I guess they are wrong and need to be fixed. You can have a look at
include/asm-generic/io.h to see that the byteswap is already done
there.

> > > +             if (*data == 0xffffffff) {
> > > +                     *data = -1;
> > > +                     return PCIBIOS_DEVICE_NOT_FOUND;
> > > +             }
> > > +     }
> > > +     return PCIBIOS_SUCCESSFUL;
> > > +}
> > > +
> > > +static int loongson3_pci_pcibios_read(struct pci_bus *bus, unsigned int
> > devfn,
> > > +                              int where, int size, u32 *val)
> > > +{
> > > +     u32 data = 0;
> > > +     int ret = loongson3_pci_config_access(PCI_ACCESS_READ,
> > > +                     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 loongson3_pci_pcibios_write(struct pci_bus *bus, unsigned
> > int devfn,
> > > +                               int where, int size, u32 val)
> > > +{
> > > +     u32 data = 0;
> > > +     int ret;
> > > +
> > > +     if (size == 4)
> > > +             data = val;
> > > +     else {
> > > +             ret = loongson3_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 = loongson3_pci_config_access(PCI_ACCESS_WRITE,
> > > +                     bus, devfn, where, &data);
> > > +
> > > +     return ret;
> > > +}
> > > +
> > > +struct pci_ops loongson_pci_ops = {
> > > +     .read = loongson3_pci_pcibios_read,
> > > +     .write = loongson3_pci_pcibios_write
> > > +};
> > > --
> > > 1.7.7.3
> > >
> > >
> >
> > --
> > Aurelien Jarno                          GPG: 1024D/F1BCDB73
> > aurelien@aurel32.net                 http://www.aurel32.net
> >
> >

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 08/12] MIPS: Loongson: Add swiotlb to support big memory (>4GB)
       [not found]     ` <CAAhV-H4h43N2OR4znwVv3miVbGkWJLapdgr9Jou1j4R8-9TRyA@mail.gmail.com>
@ 2014-01-09 22:08       ` Aurelien Jarno
       [not found]         ` <CAAhV-H7WFdt-4jYG5qPV36UWJQnSfkSa2J-3CAs2+QLqwHVhuA@mail.gmail.com>
  0 siblings, 1 reply; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-09 22:08 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Thu, Jan 09, 2014 at 06:33:48PM +0800, Huacai Chen wrote:
> On Thu, Jan 9, 2014 at 6:58 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> 
> > On Wed, Jan 08, 2014 at 10:44:24AM +0800, Huacai Chen wrote:
> > > This is probably a workaround because Loongson doesn't support DMA
> > > address above 4GB. If memory is more than 4GB, CONFIG_SWIOTLB and
> > > ZONE_DMA32 should be selected. In this way, DMA pages are allocated
> > > below 4GB preferably.
> > >
> > > However, CONFIG_SWIOTLB+ZONE_DMA32 is not enough, so, we provide a
> > > platform-specific dma_map_ops::set_dma_mask() to make sure each
> > > driver's dma_mask and coherent_dma_mask is below 32-bit.
> > >
> > > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > > Signed-off-by: Hongliang Tao <taohl@lemote.com>
> > > Signed-off-by: Hua Yan <yanh@lemote.com>
> > > ---
> > >  arch/mips/include/asm/dma-mapping.h                |    5 +
> > >  .../mips/include/asm/mach-loongson/dma-coherence.h |   22 +++-
> > >  arch/mips/loongson/common/Makefile                 |    5 +
> > >  arch/mips/loongson/common/dma-swiotlb.c            |  165
> > ++++++++++++++++++++
> > >  4 files changed, 196 insertions(+), 1 deletions(-)
> > >  create mode 100644 arch/mips/loongson/common/dma-swiotlb.c
> > >
> > > diff --git a/arch/mips/include/asm/dma-mapping.h
> > b/arch/mips/include/asm/dma-mapping.h
> > > index 84238c5..06412aa 100644
> > > --- a/arch/mips/include/asm/dma-mapping.h
> > > +++ b/arch/mips/include/asm/dma-mapping.h
> > > @@ -49,9 +49,14 @@ static inline int dma_mapping_error(struct device
> > *dev, u64 mask)
> > >  static inline int
> > >  dma_set_mask(struct device *dev, u64 mask)
> > >  {
> > > +     struct dma_map_ops *ops = get_dma_ops(dev);
> > > +
> > >       if(!dev->dma_mask || !dma_supported(dev, mask))
> > >               return -EIO;
> > >
> > > +     if (ops->set_dma_mask)
> > > +             return ops->set_dma_mask(dev, mask);
> > > +
> >
> > I think that with the changes I propose in loongson_dma_alloc_coherent,
> > this should be useless.
> >
> > >       *dev->dma_mask = mask;
> > >
> > >       return 0;
> > > diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h
> > b/arch/mips/include/asm/mach-loongson/dma-coherence.h
> > > index aeb2c05..6a90275 100644
> > > --- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
> > > +++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
> > > @@ -11,24 +11,40 @@
> > >  #ifndef __ASM_MACH_LOONGSON_DMA_COHERENCE_H
> > >  #define __ASM_MACH_LOONGSON_DMA_COHERENCE_H
> > >
> > > +#ifdef CONFIG_SWIOTLB
> > > +#include <linux/swiotlb.h>
> > > +#endif
> > > +
> > >  struct device;
> > >
> > > +extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
> > > +extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
> > >  static inline dma_addr_t plat_map_dma_mem(struct device *dev, void
> > *addr,
> > >                                         size_t size)
> > >  {
> > > +#ifdef CONFIG_CPU_LOONGSON3
> > > +     return virt_to_phys(addr);
> > > +#else
> > >       return virt_to_phys(addr) | 0x80000000;
> > > +#endif
> > >  }
> > >
> > >  static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
> > >                                              struct page *page)
> > >  {
> > > +#ifdef CONFIG_CPU_LOONGSON3
> > > +     return page_to_phys(page);
> > > +#else
> > >       return page_to_phys(page) | 0x80000000;
> > > +#endif
> > >  }
> > >
> > >  static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
> > >       dma_addr_t dma_addr)
> > >  {
> > > -#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
> > > +#if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT)
> > > +     return dma_addr;
> > > +#elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
> > >       return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr &
> > 0x0fffffff);
> > >  #else
> > >       return dma_addr & 0x7fffffff;
> > > @@ -55,7 +71,11 @@ static inline int plat_dma_supported(struct device
> > *dev, u64 mask)
> > >
> > >  static inline int plat_device_is_coherent(struct device *dev)
> > >  {
> > > +#ifdef CONFIG_DMA_NONCOHERENT
> > >       return 0;
> > > +#else
> > > +     return 1;
> > > +#endif /* CONFIG_DMA_NONCOHERENT */
> > >  }
> > >
> > >  #endif /* __ASM_MACH_LOONGSON_DMA_COHERENCE_H */
> > > diff --git a/arch/mips/loongson/common/Makefile
> > b/arch/mips/loongson/common/Makefile
> > > index 9e4484c..0bb9cc9 100644
> > > --- a/arch/mips/loongson/common/Makefile
> > > +++ b/arch/mips/loongson/common/Makefile
> > > @@ -26,3 +26,8 @@ obj-$(CONFIG_CS5536) += cs5536/
> > >  #
> > >
> > >  obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
> > > +
> > > +#
> > > +# Big Memory (SWIOTLB) Support
> > > +#
> > > +obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o
> > > diff --git a/arch/mips/loongson/common/dma-swiotlb.c
> > b/arch/mips/loongson/common/dma-swiotlb.c
> > > new file mode 100644
> > > index 0000000..9d5451b
> > > --- /dev/null
> > > +++ b/arch/mips/loongson/common/dma-swiotlb.c
> > > @@ -0,0 +1,165 @@
> > > +#include <linux/mm.h>
> > > +#include <linux/init.h>
> > > +#include <linux/dma-mapping.h>
> > > +#include <linux/scatterlist.h>
> > > +#include <linux/swiotlb.h>
> > > +#include <linux/bootmem.h>
> > > +
> > > +#include <asm/bootinfo.h>
> > > +#include <dma-coherence.h>
> > > +
> > > +static void *loongson_dma_alloc_coherent(struct device *dev, size_t
> > size,
> > > +             dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
> > > +{
> > > +     void *ret;
> > > +
> > > +     if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
> > > +             return ret;
> > > +
> > > +     /* ignore region specifiers */
> > > +     gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
> > > +
> > > +#ifdef CONFIG_ISA
> > > +     if (dev == NULL)
> > > +             gfp |= __GFP_DMA;
> > > +     else
> > > +#endif
> > > +#ifdef CONFIG_ZONE_DMA
> > > +     if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
> > > +             gfp |= __GFP_DMA;
> > > +     else
> > > +#endif
> > > +#ifdef CONFIG_ZONE_DMA32
> > > +      /* Loongson-3 only support DMA in the memory below 4GB now */
> > > +     if (dev->coherent_dma_mask < DMA_BIT_MASK(40))
> >
> > You don't want the if here. If the device has coherent_dma_mask with
> > the highest bit being the 32th one or higher, you still need
> > __GFP_DMA32 to make sure the memory will be allocated below 4GB, as
> > the Loongson 3 CPU doesn't support more than 32-bit DMA.
> >
> 32-bit DMA is probably not because of Loongson-3, but because of the
> north-bridge configuration. In our recent experiments, we can enable
> 64-bit DMA by update PMON (but it need more time to prove the stability).
> So we keep the set_dma_mask() for future. Moreover, we need a correct
> dma_mask to check the DMAablity in lib/swiotlb.c.
> 
> DMA_BIT_MASK(40) comes from Radeon GPU, if DMA-40 is enabled, it doesn't
> need to alloc pages in DMA32 zone.

The description of the patch says that a Loongson system only supports
DMA below 4GB. We doesn't care here if the limit comes from the
north-bridge configuration or of the CPU. So if the limit should be 4GB,
__GFP_DMA32 should always be set. If there is no limit, it should be set
if (dev->coherent_dma_mask < DMA_BIT_MASK(64)) as the DMA32 zone is the
biggest zone usable when the address doesn't fit in 64 bit.

In any case it is not really consistent to not limit the addresses to
32 bits here, but limit them later in set_dma_mask().

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 09/12] MIPS: Loongson: Add Loongson-3 Kconfig options
  2014-01-09 13:07     ` Alex Smith
  (?)
@ 2014-01-11 15:24     ` Aurelien Jarno
  2014-01-13  3:02       ` Huacai Chen
  -1 siblings, 1 reply; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-11 15:24 UTC (permalink / raw)
  To: Alex Smith
  Cc: Huacai Chen, Ralf Baechle, John Crispin, Steven J. Hill,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Thu, Jan 09, 2014 at 01:07:30PM +0000, Alex Smith wrote:
> On 08/01/14 02:44, Huacai Chen wrote:
> >Added Kconfig options include: Loongson-3 CPU and machine definition,
> >CPU cache features, UEFI-like firmware interface (LEFI), HT-linked PCI,
> >and big memory support.
> >
> >Signed-off-by: Huacai Chen <chenhc@lemote.com>
> >Signed-off-by: Hongliang Tao <taohl@lemote.com>
> >Signed-off-by: Hua Yan <yanh@lemote.com>
> >---
> >  arch/mips/Kconfig           |   29 +++++++++++++++++++++++++++-
> >  arch/mips/loongson/Kconfig  |   44 +++++++++++++++++++++++++++++++++++++++++++
> >  arch/mips/loongson/Platform |    1 +
> >  3 files changed, 73 insertions(+), 1 deletions(-)
> >
> >diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> >index 17cc7ff..513e941 100644
> >--- a/arch/mips/Kconfig
> >+++ b/arch/mips/Kconfig
> >@@ -1487,6 +1487,18 @@ config CPU_LOONGSON2
> >  	select CPU_SUPPORTS_HIGHMEM
> >  	select CPU_SUPPORTS_HUGEPAGES
> >
> >+config CPU_LOONGSON3
> >+	bool "Loongson 3 CPU"
> >+	depends on SYS_HAS_CPU_LOONGSON3
> >+	select CPU_SUPPORTS_64BIT_KERNEL
> >+	select CPU_SUPPORTS_HIGHMEM
> >+	select CPU_SUPPORTS_HUGEPAGES
> >+	select WEAK_ORDERING
> >+	select WEAK_REORDERING_BEYOND_LLSC
> >+	help
> >+		The Loongson 3 processor implements the MIPS III instruction set
> >+		with many extensions.
> >+
> 
> This should be moved into the "CPU type" choice block. Currently
> this appears as an option outside of that choice, and so it is
> possible to build a kernel without any CPU type selected.
> 
> Also, as Aurelien said on the previous version, shouldn't the
> comment be changed to MIPS64R2 rather than MIPS III even if you
> aren't selecting the MIPS64 CPU types for the time being? Note, if
> you replied to that comment I may not have seen it - I think the
> list is filtering your replies because they're HTML emails.
> 
> >  config CPU_LOONGSON1
> >  	bool
> >  	select CPU_MIPS32
> >@@ -1513,6 +1526,10 @@ config SYS_HAS_CPU_LOONGSON2F
> >  	select CPU_SUPPORTS_ADDRWINCFG if 64BIT
> >  	select CPU_SUPPORTS_UNCACHED_ACCELERATED
> >
> >+config SYS_HAS_CPU_LOONGSON3
> >+	bool
> >+	select CPU_SUPPORTS_CPUFREQ
> >+
> >  config SYS_HAS_CPU_LOONGSON1B
> >  	bool
> >
> >@@ -1703,7 +1720,7 @@ choice
> >
> >  config PAGE_SIZE_4KB
> >  	bool "4kB"
> >-	depends on !CPU_LOONGSON2
> >+	depends on !CPU_LOONGSON2 && !CPU_LOONGSON3
> >  	help
> >  	 This option select the standard 4kB Linux page size.  On some
> >  	 R3000-family processors this is the only available page size.  Using
> >@@ -2373,6 +2390,16 @@ config PCI
> >  	  your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
> >  	  say Y, otherwise N.
> >
> >+config HT_PCI
> >+	bool "Support for HT-linked PCI"
> >+	depends on CPU_LOONGSON3
> >+	select PCI_DOMAINS
> >+	help
> >+	  Loongson family machines use Hyper-Transport bus for inter-core
> >+	  connection and device connection. The PCI bus is a subordinate
> >+	  linked at HT. Choose Y unless you are using Loongson 2E/2F based
> >+	  machines.
> >+
> 
> Should this default to y, given that it is selected in the
> defconfig? Also, the comment referring to 2E/2F is redundant given
> that it depends on CPU_LOONGSON3 and cannot be selected on those
> machines.

I am still not sure we need such an option. This option only changes an
address in arch/mips/include/asm/mach-loongson/loongson.h:

| #if defined(CONFIG_HT_PCI)
| #define LOONGSON_PCIIO_BASE     loongson_sysconf.pci_io_base
| #else
| #define LOONGSON_PCIIO_BASE     0x1fd00000
| #endif

If both options are working on a Loongson 3 machine, it's definitely a
good idea to leave the choice to the user. That said if only the address
from loongson_sysconf.pci_io_base works on a Loongson 3 machine, this
option must always be selected and is therefore useless.

> >  config PCI_DOMAINS
> >  	bool
> >
> >diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
> >index 263beb9..4f3967c 100644
> >--- a/arch/mips/loongson/Kconfig
> >+++ b/arch/mips/loongson/Kconfig
> >@@ -59,6 +59,33 @@ config LEMOTE_MACH2F
> >
> >  	  These family machines include fuloong2f mini PC, yeeloong2f notebook,
> >  	  LingLoong allinone PC and so forth.
> >+
> >+config LEMOTE_MACH3A
> >+	bool "Lemote Loongson 3A family machines"
> >+	select ARCH_SPARSEMEM_ENABLE
> >+	select GENERIC_ISA_DMA_SUPPORT_BROKEN
> >+	select GENERIC_HARDIRQS_NO__DO_IRQ
> >+	select BOOT_ELF32
> >+	select BOARD_SCACHE
> >+	select CSRC_R4K
> >+	select CEVT_R4K
> >+	select CPU_HAS_WB
> >+	select HW_HAS_PCI
> >+	select ISA
> >+	select I8259
> >+	select IRQ_CPU
> >+	select SYS_HAS_CPU_LOONGSON3
> >+	select SYS_HAS_EARLY_PRINTK
> >+	select SYS_SUPPORTS_SMP
> >+	select SYS_SUPPORTS_64BIT_KERNEL
> >+	select SYS_SUPPORTS_HIGHMEM
> >+	select SYS_SUPPORTS_LITTLE_ENDIAN
> >+	select LOONGSON_MC146818
> >+	select ZONE_DMA32 if 64BIT
> >+	select LEFI_FIRMWARE_INTERFACE
> >+	help
> >+		Lemote Loongson 3A family machines utilize the 3A revision of
> >+		Loongson processor and RS780/SBX00 chipset.
> >  endchoice
> 
> Add "select NR_CPUS_DEFAULT_4" on here? Currently creating a
> configuration without using the loongson3_defconfig will default to
> 2, but unless I'm mistaken, all 3A machines are quad core?
> 
> >
> >  config CS5536
> >@@ -86,8 +114,24 @@ config LOONGSON_UART_BASE
> >  	default y
> >  	depends on EARLY_PRINTK || SERIAL_8250
> >
> >+config IOMMU_HELPER
> >+	bool
> >+
> >+config NEED_SG_DMA_LENGTH
> >+	bool
> >+
> >+config SWIOTLB
> >+	bool "Soft IOMMU Support for Big Memory (>4GB)"
> >+	depends on CPU_LOONGSON3
> >+	select IOMMU_HELPER
> >+	select NEED_SG_DMA_LENGTH
> >+	select NEED_DMA_MAP_STATE
> >+
> 
> Again, default to y?
> 
> Thanks,
> Alex
> 
> >  config LOONGSON_MC146818
> >  	bool
> >  	default n
> >
> >+config LEFI_FIRMWARE_INTERFACE
> >+	bool
> >+
> >  endif # MACH_LOONGSON
> >diff --git a/arch/mips/loongson/Platform b/arch/mips/loongson/Platform
> >index 29692e5..6205372 100644
> >--- a/arch/mips/loongson/Platform
> >+++ b/arch/mips/loongson/Platform
> >@@ -30,3 +30,4 @@ platform-$(CONFIG_MACH_LOONGSON) += loongson/
> >  cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely
> >  load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000
> >  load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000
> >+load-$(CONFIG_CPU_LOONGSON3) += 0xffffffff80200000
> >
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 11/12] MIPS: Loongson 3: Add CPU hotplug support
  2014-01-08  2:44 ` [PATCH V16 11/12] MIPS: Loongson 3: Add CPU hotplug support Huacai Chen
@ 2014-01-11 15:24   ` Aurelien Jarno
  0 siblings, 0 replies; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-11 15:24 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Wed, Jan 08, 2014 at 10:44:27AM +0800, Huacai Chen wrote:
> Tips of Loongson's CPU hotplug:
> 1, To fully shutdown a core in Loongson 3, the target core should go to
>    CKSEG1 and flush all L1 cache entries at first. Then, another core
>    (usually Core 0) can safely disable the clock of the target core. So
>    play_dead() call loongson3_play_dead() via CKSEG1 (both uncached and
>    unmmaped).
> 2, The default clocksource of Loongson is MIPS. Since clock source is a
>    global device, timekeeping need the CP0' Count registers of each core
>    be synchronous. Thus, when a core is up, we use a SMP_ASK_C0COUNT IPI
>    to ask Core-0's Count.
> 
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> Signed-off-by: Hua Yan <yanh@lemote.com>
> ---
>  arch/mips/include/asm/mach-loongson/irq.h      |    1 +
>  arch/mips/include/asm/mach-loongson/loongson.h |    6 +-
>  arch/mips/include/asm/smp.h                    |    1 +
>  arch/mips/loongson/Kconfig                     |    1 +
>  arch/mips/loongson/loongson-3/irq.c            |   10 ++
>  arch/mips/loongson/loongson-3/smp.c            |  171 +++++++++++++++++++++++-
>  6 files changed, 185 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/mips/include/asm/mach-loongson/irq.h b/arch/mips/include/asm/mach-loongson/irq.h
> index d2f0e2a..620b3e9 100644
> --- a/arch/mips/include/asm/mach-loongson/irq.h
> +++ b/arch/mips/include/asm/mach-loongson/irq.h
> @@ -22,6 +22,7 @@
>  
>  #endif
>  
> +extern void fixup_irqs(void);
>  extern void loongson3_ipi_interrupt(struct pt_regs *regs);
>  
>  #include_next <irq.h>
> diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
> index f185907..f3fd1eb 100644
> --- a/arch/mips/include/asm/mach-loongson/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson/loongson.h
> @@ -249,6 +249,9 @@ static inline void do_perfcnt_IRQ(void)
>  #define LOONGSON_PXARB_CFG		LOONGSON_REG(LOONGSON_REGBASE + 0x68)
>  #define LOONGSON_PXARB_STATUS		LOONGSON_REG(LOONGSON_REGBASE + 0x6c)
>  
> +/* Chip Config */
> +#define LOONGSON_CHIPCFG0		LOONGSON_REG(LOONGSON_REGBASE + 0x80)
> +
>  /* pcimap */
>  
>  #define LOONGSON_PCIMAP_PCIMAP_LO0	0x0000003f
> @@ -264,9 +267,6 @@ static inline void do_perfcnt_IRQ(void)
>  #ifdef CONFIG_CPU_SUPPORTS_CPUFREQ
>  #include <linux/cpufreq.h>
>  extern struct cpufreq_frequency_table loongson2_clockmod_table[];
> -
> -/* Chip Config */
> -#define LOONGSON_CHIPCFG0		LOONGSON_REG(LOONGSON_REGBASE + 0x80)
>  #endif
>  
>  /*
> diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
> index eb60087..efa02ac 100644
> --- a/arch/mips/include/asm/smp.h
> +++ b/arch/mips/include/asm/smp.h
> @@ -42,6 +42,7 @@ extern int __cpu_logical_map[NR_CPUS];
>  #define SMP_ICACHE_FLUSH	0x4
>  /* Used by kexec crashdump to save all cpu's state */
>  #define SMP_DUMP		0x8
> +#define SMP_ASK_C0COUNT		0x10
>  
>  extern volatile cpumask_t cpu_callin_map;
>  
> diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
> index 4f3967c..f29e604 100644
> --- a/arch/mips/loongson/Kconfig
> +++ b/arch/mips/loongson/Kconfig
> @@ -77,6 +77,7 @@ config LEMOTE_MACH3A
>  	select SYS_HAS_CPU_LOONGSON3
>  	select SYS_HAS_EARLY_PRINTK
>  	select SYS_SUPPORTS_SMP
> +	select SYS_SUPPORTS_HOTPLUG_CPU
>  	select SYS_SUPPORTS_64BIT_KERNEL
>  	select SYS_SUPPORTS_HIGHMEM
>  	select SYS_SUPPORTS_LITTLE_ENDIAN
> diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
> index d8920a8..d457366 100644
> --- a/arch/mips/loongson/loongson-3/irq.c
> +++ b/arch/mips/loongson/loongson-3/irq.c
> @@ -128,3 +128,13 @@ void __init mach_init_irq(void)
>  
>  	set_c0_status(STATUSF_IP2 | STATUSF_IP6);
>  }
> +
> +#ifdef CONFIG_HOTPLUG_CPU
> +
> +void fixup_irqs(void)
> +{
> +	irq_cpu_offline();
> +	clear_c0_status(ST0_IM);
> +}
> +
> +#endif
> diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
> index a264bcb..059ef94 100644
> --- a/arch/mips/loongson/loongson-3/smp.c
> +++ b/arch/mips/loongson/loongson-3/smp.c
> @@ -26,10 +26,14 @@
>  #include <asm/time.h>
>  #include <asm/clock.h>
>  #include <asm/tlbflush.h>
> +#include <asm/cacheflush.h>
>  #include <loongson.h>
>  
>  #include "smp.h"
>  
> +DEFINE_PER_CPU(int, cpu_state);
> +DEFINE_PER_CPU(uint32_t, core0_c0count);
> +
>  /* read a 64bit value from ipi register */
>  uint64_t loongson3_ipi_read64(void *addr)
>  {
> @@ -170,8 +174,8 @@ loongson3_send_ipi_mask(const struct cpumask *mask, unsigned int action)
>  
>  void loongson3_ipi_interrupt(struct pt_regs *regs)
>  {
> -	int cpu = smp_processor_id();
> -	unsigned int action;
> +	int i, cpu = smp_processor_id();
> +	unsigned int action, c0count;
>  
>  	/* Load the ipi register to figure out what we're supposed to do */
>  	action = loongson3_ipi_read32(ipi_status0_regs[cpu]);
> @@ -184,14 +188,24 @@ void loongson3_ipi_interrupt(struct pt_regs *regs)
>  
>  	if (action & SMP_CALL_FUNCTION)
>  		smp_call_function_interrupt();
> +
> +	if (action & SMP_ASK_C0COUNT) {
> +		BUG_ON(cpu != 0);
> +		c0count = read_c0_count();
> +		for (i = 1; i < loongson_sysconf.nr_cpus; i++)
> +			per_cpu(core0_c0count, i) = c0count;
> +	}
>  }
>  
> +#define MAX_LOOPS 1000
>  /*
>   * SMP init and finish on secondary CPUs
>   */
>  void loongson3_init_secondary(void)
>  {
>  	int i;
> +	uint32_t initcount;
> +	unsigned int cpu = smp_processor_id();
>  	unsigned int imask = STATUSF_IP7 | STATUSF_IP6 |
>  			     STATUSF_IP3 | STATUSF_IP2;
>  
> @@ -200,6 +214,21 @@ void loongson3_init_secondary(void)
>  
>  	for (i = 0; i < loongson_sysconf.nr_cpus; i++)
>  		loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]);
> +
> +	per_cpu(cpu_state, cpu) = CPU_ONLINE;
> +
> +	i = 0;
> +	__get_cpu_var(core0_c0count) = 0;
> +	loongson3_send_ipi_single(0, SMP_ASK_C0COUNT);
> +	while (!__get_cpu_var(core0_c0count)) {
> +		i++;
> +		cpu_relax();
> +	}
> +
> +	if (i > MAX_LOOPS)
> +		i = MAX_LOOPS;
> +	initcount = __get_cpu_var(core0_c0count) + i;
> +	write_c0_count(initcount);
>  }
>  
>  void loongson3_smp_finish(void)
> @@ -234,6 +263,8 @@ void __init loongson3_smp_setup(void)
>  
>  void __init loongson3_prepare_cpus(unsigned int max_cpus)
>  {
> +	init_cpu_present(cpu_possible_mask);
> +	per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
>  }
>  
>  /*
> @@ -267,6 +298,138 @@ void __init loongson3_cpus_done(void)
>  {
>  }
>  
> +#ifdef CONFIG_HOTPLUG_CPU
> +
> +static int loongson3_cpu_disable(void)
> +{
> +	unsigned long flags;
> +	unsigned int cpu = smp_processor_id();
> +
> +	if (cpu == 0)
> +		return -EBUSY;
> +
> +	set_cpu_online(cpu, false);
> +	cpu_clear(cpu, cpu_callin_map);
> +	local_irq_save(flags);
> +	fixup_irqs();
> +	local_irq_restore(flags);
> +	flush_cache_all();
> +	local_flush_tlb_all();
> +
> +	return 0;
> +}
> +
> +
> +static void loongson3_cpu_die(unsigned int cpu)
> +{
> +	while (per_cpu(cpu_state, cpu) != CPU_DEAD)
> +		cpu_relax();
> +
> +	mb();
> +}
> +
> +/* To shutdown a core in Loongson 3, the target core should go to CKSEG1 and
> + * flush all L1 entries at first. Then, another core (usually Core 0) can
> + * safely disable the clock of the target core. loongson3_play_dead() is
> + * called via CKSEG1 (uncached and unmmaped) */
> +void loongson3_play_dead(int *state_addr)

Use static maybe?

> +{
> +	__asm__ __volatile__(
> +		"   .set push                     \n"
> +		"   .set noreorder                \n"
> +		"   li $t0, 0x80000000            \n" /* KSEG0 */
> +		"   move $t1, %0                  \n" /* num of L1 entries */
> +		"1: cache 0, 0($t0)               \n" /* flush L1 ICache */
> +		"   cache 0, 1($t0)               \n"
> +		"   cache 0, 2($t0)               \n"
> +		"   cache 0, 3($t0)               \n"
> +		"   cache 1, 0($t0)               \n" /* flush L1 DCache */
> +		"   cache 1, 1($t0)               \n"
> +		"   cache 1, 2($t0)               \n"
> +		"   cache 1, 3($t0)               \n"
> +		"   addiu $t0, $t0, 0x20          \n"
> +		"   bnez  $t1, 1b                 \n"
> +		"   addiu $t1, $t1, -1            \n"
> +		"   li    $t0, 0x7                \n" /* *state_addr = CPU_DEAD; */
> +		"   sw    $t0, 0($a0)             \n"
> +		"   sync                          \n"
> +		"   cache 21, 0($a0)              \n" /* flush entry of *state_addr */
> +		"   .set pop                      \n"
> +		: /* No Output */
> +		: "r" (cpu_data[0].dcache.sets));

It looks better now that the cash size is not hardcoded. That said could
it be possible to use the corresponding cpu number instead of accessing
the value of cpu 0?

> +
> +	__asm__ __volatile__(
> +		"   .set push                     \n"
> +		"   .set noreorder                \n"
> +		"   .set mips64                   \n"
> +		"   mfc0  $t2, $15, 1             \n"
> +		"   andi  $t2, 0x3ff              \n"
> +		"   dli   $t0, 0x900000003ff01000 \n"
> +		"   andi  $t3, $t2, 0x3           \n"
> +		"   sll   $t3, 8                  \n"  /* get cpu id */
> +		"   or    $t0, $t0, $t3           \n"
> +		"   andi  $t1, $t2, 0xc           \n"
> +		"   dsll  $t1, 42                 \n"  /* get node id */
> +		"   or    $t0, $t0, $t1           \n"
> +		"1: li    $a0, 0x100              \n"  /* wait for init loop */
> +		"2: bnez  $a0, 2b                 \n"  /* idle loop */

As you told me this loop is there to limit the mailbox access rate.
Maybe it should worth noting that in the comment instead of "idle loop".

> +		"   addiu $a0, -1                 \n"
> +		"   lw    $v0, 0x20($t0)          \n"  /* get PC via mailbox */
> +		"   beqz  $v0, 1b                 \n"
> +		"   nop                           \n"
> +		"   ld    $sp, 0x28($t0)          \n"  /* get SP via mailbox */
> +		"   ld    $gp, 0x30($t0)          \n"  /* get GP via mailbox */
> +		"   ld    $a1, 0x38($t0)          \n"
> +		"   jr    $v0                     \n"  /* jump to initial PC */
> +		"   nop                           \n"
> +		"   .set pop                      \n");
> +}
> +
> +void play_dead(void)
> +{
> +	int *state_addr;
> +	unsigned int cpu = smp_processor_id();
> +	void (*play_dead_at_ckseg1)(int *);
> +
> +	idle_task_exit();
> +	play_dead_at_ckseg1 =
> +		(void *)CKSEG1ADDR((unsigned long)loongson3_play_dead);
> +	state_addr = &per_cpu(cpu_state, cpu);
> +	mb();
> +	play_dead_at_ckseg1(state_addr);
> +}
> +
> +#define CPU_POST_DEAD_FROZEN	(CPU_POST_DEAD | CPU_TASKS_FROZEN)
> +static int loongson3_cpu_callback(struct notifier_block *nfb,
> +	unsigned long action, void *hcpu)
> +{
> +	unsigned int cpu = (unsigned long)hcpu;
> +
> +	switch (action) {
> +	case CPU_POST_DEAD:
> +	case CPU_POST_DEAD_FROZEN:
> +		pr_info("Disable clock for CPU#%d\n", cpu);
> +		LOONGSON_CHIPCFG0 &= ~(1 << (12 + cpu));
> +		break;
> +	case CPU_UP_PREPARE:
> +	case CPU_UP_PREPARE_FROZEN:
> +		pr_info("Enable clock for CPU#%d\n", cpu);
> +		LOONGSON_CHIPCFG0 |= 1 << (12 + cpu);
> +		break;
> +	}
> +
> +	return NOTIFY_OK;
> +}
> +
> +static int register_loongson3_notifier(void)
> +{
> +	hotcpu_notifier(loongson3_cpu_callback, 0);
> +	return 0;
> +}
> +early_initcall(register_loongson3_notifier);
> +
> +#endif
> +
>  struct plat_smp_ops loongson3_smp_ops = {
>  	.send_ipi_single = loongson3_send_ipi_single,
>  	.send_ipi_mask = loongson3_send_ipi_mask,
> @@ -276,4 +439,8 @@ struct plat_smp_ops loongson3_smp_ops = {
>  	.boot_secondary = loongson3_boot_secondary,
>  	.smp_setup = loongson3_smp_setup,
>  	.prepare_cpus = loongson3_prepare_cpus,
> +#ifdef CONFIG_HOTPLUG_CPU
> +	.cpu_disable = loongson3_cpu_disable,
> +	.cpu_die = loongson3_cpu_die,
> +#endif
>  };
> -- 
> 1.7.7.3
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 08/12] MIPS: Loongson: Add swiotlb to support big memory (>4GB)
       [not found]         ` <CAAhV-H7WFdt-4jYG5qPV36UWJQnSfkSa2J-3CAs2+QLqwHVhuA@mail.gmail.com>
@ 2014-01-11 15:24           ` Aurelien Jarno
  0 siblings, 0 replies; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-11 15:24 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Fri, Jan 10, 2014 at 03:45:13PM +0800, Huacai Chen wrote:
> On Fri, Jan 10, 2014 at 6:08 AM, Aurelien Jarno <aurelien@aurel32.net>wrote:
> 
> > On Thu, Jan 09, 2014 at 06:33:48PM +0800, Huacai Chen wrote:
> > > On Thu, Jan 9, 2014 at 6:58 AM, Aurelien Jarno <aurelien@aurel32.net>
> > wrote:
> > >
> > > > On Wed, Jan 08, 2014 at 10:44:24AM +0800, Huacai Chen wrote:
> > > > > This is probably a workaround because Loongson doesn't support DMA
> > > > > address above 4GB. If memory is more than 4GB, CONFIG_SWIOTLB and
> > > > > ZONE_DMA32 should be selected. In this way, DMA pages are allocated
> > > > > below 4GB preferably.
> > > > >
> > > > > However, CONFIG_SWIOTLB+ZONE_DMA32 is not enough, so, we provide a
> > > > > platform-specific dma_map_ops::set_dma_mask() to make sure each
> > > > > driver's dma_mask and coherent_dma_mask is below 32-bit.
> > > > >
> > > > > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > > > > Signed-off-by: Hongliang Tao <taohl@lemote.com>
> > > > > Signed-off-by: Hua Yan <yanh@lemote.com>
> > > > > ---
> > > > >  arch/mips/include/asm/dma-mapping.h                |    5 +
> > > > >  .../mips/include/asm/mach-loongson/dma-coherence.h |   22 +++-
> > > > >  arch/mips/loongson/common/Makefile                 |    5 +
> > > > >  arch/mips/loongson/common/dma-swiotlb.c            |  165
> > > > ++++++++++++++++++++
> > > > >  4 files changed, 196 insertions(+), 1 deletions(-)
> > > > >  create mode 100644 arch/mips/loongson/common/dma-swiotlb.c
> > > > >
> > > > > diff --git a/arch/mips/include/asm/dma-mapping.h
> > > > b/arch/mips/include/asm/dma-mapping.h
> > > > > index 84238c5..06412aa 100644
> > > > > --- a/arch/mips/include/asm/dma-mapping.h
> > > > > +++ b/arch/mips/include/asm/dma-mapping.h
> > > > > @@ -49,9 +49,14 @@ static inline int dma_mapping_error(struct device
> > > > *dev, u64 mask)
> > > > >  static inline int
> > > > >  dma_set_mask(struct device *dev, u64 mask)
> > > > >  {
> > > > > +     struct dma_map_ops *ops = get_dma_ops(dev);
> > > > > +
> > > > >       if(!dev->dma_mask || !dma_supported(dev, mask))
> > > > >               return -EIO;
> > > > >
> > > > > +     if (ops->set_dma_mask)
> > > > > +             return ops->set_dma_mask(dev, mask);
> > > > > +
> > > >
> > > > I think that with the changes I propose in loongson_dma_alloc_coherent,
> > > > this should be useless.
> > > >
> > > > >       *dev->dma_mask = mask;
> > > > >
> > > > >       return 0;
> > > > > diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h
> > > > b/arch/mips/include/asm/mach-loongson/dma-coherence.h
> > > > > index aeb2c05..6a90275 100644
> > > > > --- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
> > > > > +++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
> > > > > @@ -11,24 +11,40 @@
> > > > >  #ifndef __ASM_MACH_LOONGSON_DMA_COHERENCE_H
> > > > >  #define __ASM_MACH_LOONGSON_DMA_COHERENCE_H
> > > > >
> > > > > +#ifdef CONFIG_SWIOTLB
> > > > > +#include <linux/swiotlb.h>
> > > > > +#endif
> > > > > +
> > > > >  struct device;
> > > > >
> > > > > +extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t
> > paddr);
> > > > > +extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t
> > daddr);
> > > > >  static inline dma_addr_t plat_map_dma_mem(struct device *dev, void
> > > > *addr,
> > > > >                                         size_t size)
> > > > >  {
> > > > > +#ifdef CONFIG_CPU_LOONGSON3
> > > > > +     return virt_to_phys(addr);
> > > > > +#else
> > > > >       return virt_to_phys(addr) | 0x80000000;
> > > > > +#endif
> > > > >  }
> > > > >
> > > > >  static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
> > > > >                                              struct page *page)
> > > > >  {
> > > > > +#ifdef CONFIG_CPU_LOONGSON3
> > > > > +     return page_to_phys(page);
> > > > > +#else
> > > > >       return page_to_phys(page) | 0x80000000;
> > > > > +#endif
> > > > >  }
> > > > >
> > > > >  static inline unsigned long plat_dma_addr_to_phys(struct device
> > *dev,
> > > > >       dma_addr_t dma_addr)
> > > > >  {
> > > > > -#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
> > > > > +#if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT)
> > > > > +     return dma_addr;
> > > > > +#elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
> > > > >       return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr &
> > > > 0x0fffffff);
> > > > >  #else
> > > > >       return dma_addr & 0x7fffffff;
> > > > > @@ -55,7 +71,11 @@ static inline int plat_dma_supported(struct device
> > > > *dev, u64 mask)
> > > > >
> > > > >  static inline int plat_device_is_coherent(struct device *dev)
> > > > >  {
> > > > > +#ifdef CONFIG_DMA_NONCOHERENT
> > > > >       return 0;
> > > > > +#else
> > > > > +     return 1;
> > > > > +#endif /* CONFIG_DMA_NONCOHERENT */
> > > > >  }
> > > > >
> > > > >  #endif /* __ASM_MACH_LOONGSON_DMA_COHERENCE_H */
> > > > > diff --git a/arch/mips/loongson/common/Makefile
> > > > b/arch/mips/loongson/common/Makefile
> > > > > index 9e4484c..0bb9cc9 100644
> > > > > --- a/arch/mips/loongson/common/Makefile
> > > > > +++ b/arch/mips/loongson/common/Makefile
> > > > > @@ -26,3 +26,8 @@ obj-$(CONFIG_CS5536) += cs5536/
> > > > >  #
> > > > >
> > > > >  obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
> > > > > +
> > > > > +#
> > > > > +# Big Memory (SWIOTLB) Support
> > > > > +#
> > > > > +obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o
> > > > > diff --git a/arch/mips/loongson/common/dma-swiotlb.c
> > > > b/arch/mips/loongson/common/dma-swiotlb.c
> > > > > new file mode 100644
> > > > > index 0000000..9d5451b
> > > > > --- /dev/null
> > > > > +++ b/arch/mips/loongson/common/dma-swiotlb.c
> > > > > @@ -0,0 +1,165 @@
> > > > > +#include <linux/mm.h>
> > > > > +#include <linux/init.h>
> > > > > +#include <linux/dma-mapping.h>
> > > > > +#include <linux/scatterlist.h>
> > > > > +#include <linux/swiotlb.h>
> > > > > +#include <linux/bootmem.h>
> > > > > +
> > > > > +#include <asm/bootinfo.h>
> > > > > +#include <dma-coherence.h>
> > > > > +
> > > > > +static void *loongson_dma_alloc_coherent(struct device *dev, size_t
> > > > size,
> > > > > +             dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs
> > *attrs)
> > > > > +{
> > > > > +     void *ret;
> > > > > +
> > > > > +     if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
> > > > > +             return ret;
> > > > > +
> > > > > +     /* ignore region specifiers */
> > > > > +     gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
> > > > > +
> > > > > +#ifdef CONFIG_ISA
> > > > > +     if (dev == NULL)
> > > > > +             gfp |= __GFP_DMA;
> > > > > +     else
> > > > > +#endif
> > > > > +#ifdef CONFIG_ZONE_DMA
> > > > > +     if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
> > > > > +             gfp |= __GFP_DMA;
> > > > > +     else
> > > > > +#endif
> > > > > +#ifdef CONFIG_ZONE_DMA32
> > > > > +      /* Loongson-3 only support DMA in the memory below 4GB now */
> > > > > +     if (dev->coherent_dma_mask < DMA_BIT_MASK(40))
> > > >
> > > > You don't want the if here. If the device has coherent_dma_mask with
> > > > the highest bit being the 32th one or higher, you still need
> > > > __GFP_DMA32 to make sure the memory will be allocated below 4GB, as
> > > > the Loongson 3 CPU doesn't support more than 32-bit DMA.
> > > >
> > > 32-bit DMA is probably not because of Loongson-3, but because of the
> > > north-bridge configuration. In our recent experiments, we can enable
> > > 64-bit DMA by update PMON (but it need more time to prove the stability).
> > > So we keep the set_dma_mask() for future. Moreover, we need a correct
> > > dma_mask to check the DMAablity in lib/swiotlb.c.
> > >
> > > DMA_BIT_MASK(40) comes from Radeon GPU, if DMA-40 is enabled, it doesn't
> > > need to alloc pages in DMA32 zone.
> >
> 
> > The description of the patch says that a Loongson system only supports
> > DMA below 4GB. We doesn't care here if the limit comes from the
> > north-bridge configuration or of the CPU. So if the limit should be 4GB,
> > __GFP_DMA32 should always be set. If there is no limit, it should be set
> > if (dev->coherent_dma_mask < DMA_BIT_MASK(64)) as the DMA32 zone is the
> > biggest zone usable when the address doesn't fit in 64 bit.
> >
> > In any case it is not really consistent to not limit the addresses to
> > 32 bits here, but limit them later in set_dma_mask().
> >
> I still think set_dma_mask() is needed. Of course we can set GFP_DMA32 in
> when alloc a page, but DMA32 zone is limited, what will happen if alloc a
> page in DMA32 zone fails? In current design, if it fails, we will alloc a
> page above 4GB and use swiotlb to bounce the page.

Yes it is exactly how swiotlb should work. The memory should be
allocated *if possible* in the DMA32 zone, and if it fails swiotlb is
used to bounce the page. However bouncing the page has a cost that
should be avoided. Not specifying GFP_DMA32, means that the memory
might be allocated anywhere, and *if we are lucky* it will be in the
DAM32 zone where not bounce buffer is needed.

> Moreover, DMA include alloc()/free() API and map_page()/unmap_page() API.
> For alloc()/free(), GFP_DMA32 can resove most of problems. However, for
> map_page()/unmap_page(), the page is probably allocated before map_page()
> and without GFP_DMA32, so cannot do DMA directly (need swiotlb to bounce).
> In this situation, device's dma_mask is used to distinguish whether bounce
> is needed (see dma_capable() which defined in
> arch/mips/include/asm/dma-mapping.h and used in lib/swiotlb.c).

Thanks for your explanation, you have convinced me that a set_dma_mask
is indeed needed. That said I do wonder if it won't be better
performance wise to replace dma_set_mask by something like:

  static inline int dma_set_mask(struct device *dev, u64 mask)
  {
      return get_dma_ops(dev)->set_dma_mask(dev, mask);
  }

And to provide a default set_dma_mask function in mm/dma-default.c.

Does anybody have an opinion about that?

> Maybe my commit message is not clear, the fact is Loongson-3A can only do
> DMA *directly* below 4GB, but can use memory above 4GB to do DMA indirectly
> (via swiotlb).

As said above, even if the use of swiotlb is possible, it has a cost
(the memory has to be copied after the DMA transfer) that should be
avoided as much as possible. That's why GFP_DMA32 should always be
specified in loongson_dma_alloc_coherent.

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 08/12] MIPS: Loongson: Add swiotlb to support big memory (>4GB)
       [not found]     ` <CAAhV-H7ZO0gNzQ5wQ-yD=NiP2AJrc3-bWLXHo-HDngf27c9+gQ@mail.gmail.com>
@ 2014-01-11 15:25       ` Aurelien Jarno
  2014-01-12  9:12         ` Huacai Chen
  0 siblings, 1 reply; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-11 15:25 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Alex Smith, Ralf Baechle, John Crispin, Steven J. Hill,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Sat, Jan 11, 2014 at 08:50:25PM +0800, Huacai Chen wrote:
> On Thu, Jan 9, 2014 at 8:56 PM, Alex Smith <alex.smith@imgtec.com> wrote:
> 
> > On 08/01/14 02:44, Huacai Chen wrote:
> >
> >> This is probably a workaround because Loongson doesn't support DMA
> >> address above 4GB. If memory is more than 4GB, CONFIG_SWIOTLB and
> >> ZONE_DMA32 should be selected. In this way, DMA pages are allocated
> >> below 4GB preferably.
> >>
> >> However, CONFIG_SWIOTLB+ZONE_DMA32 is not enough, so, we provide a
> >> platform-specific dma_map_ops::set_dma_mask() to make sure each
> >> driver's dma_mask and coherent_dma_mask is below 32-bit.
> >>
> >> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> >> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> >> Signed-off-by: Hua Yan <yanh@lemote.com>
> >> ---
> >>   arch/mips/include/asm/dma-mapping.h                |    5 +
> >>   .../mips/include/asm/mach-loongson/dma-coherence.h |   22 +++-
> >>   arch/mips/loongson/common/Makefile                 |    5 +
> >>   arch/mips/loongson/common/dma-swiotlb.c            |  165
> >> ++++++++++++++++++++
> >>   4 files changed, 196 insertions(+), 1 deletions(-)
> >>   create mode 100644 arch/mips/loongson/common/dma-swiotlb.c
> >>
> >> diff --git a/arch/mips/include/asm/dma-mapping.h
> >> b/arch/mips/include/asm/dma-mapping.h
> >> index 84238c5..06412aa 100644
> >> --- a/arch/mips/include/asm/dma-mapping.h
> >> +++ b/arch/mips/include/asm/dma-mapping.h
> >> @@ -49,9 +49,14 @@ static inline int dma_mapping_error(struct device
> >> *dev, u64 mask)
> >>   static inline int
> >>   dma_set_mask(struct device *dev, u64 mask)
> >>   {
> >> +       struct dma_map_ops *ops = get_dma_ops(dev);
> >> +
> >>         if(!dev->dma_mask || !dma_supported(dev, mask))
> >>                 return -EIO;
> >>
> >> +       if (ops->set_dma_mask)
> >> +               return ops->set_dma_mask(dev, mask);
> >> +
> >>         *dev->dma_mask = mask;
> >>
> >>         return 0;
> >> diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h
> >> b/arch/mips/include/asm/mach-loongson/dma-coherence.h
> >> index aeb2c05..6a90275 100644
> >> --- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
> >> +++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
> >> @@ -11,24 +11,40 @@
> >>   #ifndef __ASM_MACH_LOONGSON_DMA_COHERENCE_H
> >>   #define __ASM_MACH_LOONGSON_DMA_COHERENCE_H
> >>
> >> +#ifdef CONFIG_SWIOTLB
> >> +#include <linux/swiotlb.h>
> >> +#endif
> >> +
> >>   struct device;
> >>
> >> +extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
> >> +extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
> >>   static inline dma_addr_t plat_map_dma_mem(struct device *dev, void
> >> *addr,
> >>                                           size_t size)
> >>   {
> >> +#ifdef CONFIG_CPU_LOONGSON3
> >> +       return virt_to_phys(addr);
> >> +#else
> >>         return virt_to_phys(addr) | 0x80000000;
> >> +#endif
> >>   }
> >>
> >>   static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
> >>                                                struct page *page)
> >>   {
> >> +#ifdef CONFIG_CPU_LOONGSON3
> >> +       return page_to_phys(page);
> >> +#else
> >>         return page_to_phys(page) | 0x80000000;
> >> +#endif
> >>   }
> >>
> >>   static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
> >>         dma_addr_t dma_addr)
> >>   {
> >> -#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
> >> +#if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT)
> >> +       return dma_addr;
> >> +#elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
> >>         return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr &
> >> 0x0fffffff);
> >>   #else
> >>         return dma_addr & 0x7fffffff;
> >> @@ -55,7 +71,11 @@ static inline int plat_dma_supported(struct device
> >> *dev, u64 mask)
> >>
> >>   static inline int plat_device_is_coherent(struct device *dev)
> >>   {
> >> +#ifdef CONFIG_DMA_NONCOHERENT
> >>         return 0;
> >> +#else
> >> +       return 1;
> >> +#endif /* CONFIG_DMA_NONCOHERENT */
> >>   }
> >>
> >>   #endif /* __ASM_MACH_LOONGSON_DMA_COHERENCE_H */
> >> diff --git a/arch/mips/loongson/common/Makefile
> >> b/arch/mips/loongson/common/Makefile
> >> index 9e4484c..0bb9cc9 100644
> >> --- a/arch/mips/loongson/common/Makefile
> >> +++ b/arch/mips/loongson/common/Makefile
> >> @@ -26,3 +26,8 @@ obj-$(CONFIG_CS5536) += cs5536/
> >>   #
> >>
> >>   obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
> >> +
> >> +#
> >> +# Big Memory (SWIOTLB) Support
> >> +#
> >> +obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o
> >> diff --git a/arch/mips/loongson/common/dma-swiotlb.c
> >> b/arch/mips/loongson/common/dma-swiotlb.c
> >> new file mode 100644
> >> index 0000000..9d5451b
> >> --- /dev/null
> >> +++ b/arch/mips/loongson/common/dma-swiotlb.c
> >> @@ -0,0 +1,165 @@
> >> +#include <linux/mm.h>
> >> +#include <linux/init.h>
> >> +#include <linux/dma-mapping.h>
> >> +#include <linux/scatterlist.h>
> >> +#include <linux/swiotlb.h>
> >> +#include <linux/bootmem.h>
> >> +
> >> +#include <asm/bootinfo.h>
> >> +#include <dma-coherence.h>
> >> +
> >> +static void *loongson_dma_alloc_coherent(struct device *dev, size_t
> >> size,
> >> +               dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs
> >> *attrs)
> >> +{
> >> +       void *ret;
> >> +
> >> +       if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
> >> +               return ret;
> >> +
> >> +       /* ignore region specifiers */
> >> +       gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
> >> +
> >> +#ifdef CONFIG_ISA
> >> +       if (dev == NULL)
> >> +               gfp |= __GFP_DMA;
> >> +       else
> >> +#endif
> >> +#ifdef CONFIG_ZONE_DMA
> >> +       if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
> >> +               gfp |= __GFP_DMA;
> >> +       else
> >> +#endif
> >> +#ifdef CONFIG_ZONE_DMA32
> >> +        /* Loongson-3 only support DMA in the memory below 4GB now */
> >> +       if (dev->coherent_dma_mask < DMA_BIT_MASK(40))
> >> +               gfp |= __GFP_DMA32;
> >> +       else
> >> +#endif
> >> +       ;
> >> +       gfp |= __GFP_NORETRY;
> >> +
> >> +       ret = swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
> >> +       mb();
> >> +       return ret;
> >> +}
> >> +
> >> +static void loongson_dma_free_coherent(struct device *dev, size_t size,
> >> +               void *vaddr, dma_addr_t dma_handle, struct dma_attrs
> >> *attrs)
> >> +{
> >> +       int order = get_order(size);
> >> +
> >> +       if (dma_release_from_coherent(dev, order, vaddr))
> >> +               return;
> >> +
> >> +       swiotlb_free_coherent(dev, size, vaddr, dma_handle);
> >> +}
> >> +
> >> +static dma_addr_t loongson_dma_map_page(struct device *dev, struct page
> >> *page,
> >> +                               unsigned long offset, size_t size,
> >> +                               enum dma_data_direction dir,
> >> +                               struct dma_attrs *attrs)
> >> +{
> >> +       dma_addr_t daddr = swiotlb_map_page(dev, page, offset, size,
> >> +                                       dir, attrs);
> >> +       mb();
> >> +       return daddr;
> >> +}
> >> +
> >> +static int loongson_dma_map_sg(struct device *dev, struct scatterlist
> >> *sg,
> >> +                               int nents, enum dma_data_direction dir,
> >> +                               struct dma_attrs *attrs)
> >> +{
> >> +       int r = swiotlb_map_sg_attrs(dev, sg, nents, dir, NULL);
> >> +       mb();
> >> +
> >> +       return r;
> >> +}
> >> +
> >> +static void loongson_dma_sync_single_for_device(struct device *dev,
> >> +                               dma_addr_t dma_handle, size_t size,
> >> +                               enum dma_data_direction dir)
> >> +{
> >> +       swiotlb_sync_single_for_device(dev, dma_handle, size, dir);
> >> +       mb();
> >> +}
> >> +
> >> +static void loongson_dma_sync_sg_for_device(struct device *dev,
> >> +                               struct scatterlist *sg, int nents,
> >> +                               enum dma_data_direction dir)
> >> +{
> >> +       swiotlb_sync_sg_for_device(dev, sg, nents, dir);
> >> +       mb();
> >> +}
> >> +
> >> +static dma_addr_t
> >> +loongson_unity_phys_to_dma(struct device *dev, phys_addr_t paddr)
> >> +{
> >> +       return paddr;
> >> +}
> >> +
> >> +static phys_addr_t
> >> +loongson_unity_dma_to_phys(struct device *dev, dma_addr_t daddr)
> >> +{
> >> +       return daddr;
> >> +}
> >> +
> >> +struct loongson_dma_map_ops {
> >> +       struct dma_map_ops dma_map_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);
> >> +};
> >> +
> >> +dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
> >> +{
> >> +       struct loongson_dma_map_ops *ops = container_of(get_dma_ops(dev),
> >> +                               struct loongson_dma_map_ops, dma_map_ops);
> >> +
> >> +       return ops->phys_to_dma(dev, paddr);
> >> +}
> >> +
> >> +phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
> >> +{
> >> +       struct loongson_dma_map_ops *ops = container_of(get_dma_ops(dev),
> >> +                               struct loongson_dma_map_ops, dma_map_ops);
> >> +
> >> +       return ops->dma_to_phys(dev, daddr);
> >> +}
> >>
> >
> > This seems a little bit convoluted. Since phys_to_dma and dma_to_phys will
> > always end up calling the loongson_unity_ functions, I don't see any point
> > in having the loongson_dma_map_ops structure to point to them. You can just
> > implement phys_to_dma and dma_to_phys as inlines in
> > mach-loongson/dma-coherence.h.
> >
> This part comes from arch/mips/cavium-octeon/dma-octeon.c, I think this is
> needed in future.

On Cavium Octeon you have different mappings depending on the CPU, but
this is not the case on Loongson 3A. So I think that Alex is right and
that it can be simplified.

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 02/12] MIPS: Loongson: Add basic Loongson-3 CPU support
  2014-01-09 21:36       ` Aurelien Jarno
@ 2014-01-12  9:03         ` Huacai Chen
  2014-01-12  9:57           ` Aurelien Jarno
  0 siblings, 1 reply; 55+ messages in thread
From: Huacai Chen @ 2014-01-12  9:03 UTC (permalink / raw)
  To: Aurelien Jarno
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Fri, Jan 10, 2014 at 5:36 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> On Thu, Jan 09, 2014 at 04:30:54PM +0800, Huacai Chen wrote:
>> On Thu, Jan 9, 2014 at 3:58 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
>>
>> > On Wed, Jan 08, 2014 at 10:44:18AM +0800, Huacai Chen wrote:
>> > > Basic Loongson-3 CPU support include CPU probing and TLB/cache
>> > > initializing.
>> > >
>> > > Signed-off-by: Huacai Chen <chenhc@lemote.com>
>> > > Signed-off-by: Hongliang Tao <taohl@lemote.com>
>> > > Signed-off-by: Hua Yan <yanh@lemote.com>
>> > > ---
>> > >  arch/mips/include/asm/cpu-type.h |    4 ++
>> > >  arch/mips/kernel/cpu-probe.c     |   14 ++++++--
>> > >  arch/mips/mm/c-r4k.c             |   59
>> > ++++++++++++++++++++++++++++++++++++++
>> > >  arch/mips/mm/tlb-r4k.c           |    5 ++-
>> > >  arch/mips/mm/tlbex.c             |    1 +
>> > >  5 files changed, 77 insertions(+), 6 deletions(-)
>> > >
>> > > diff --git a/arch/mips/include/asm/cpu-type.h
>> > b/arch/mips/include/asm/cpu-type.h
>> > > index 4a402cc..a591e63 100644
>> > > --- a/arch/mips/include/asm/cpu-type.h
>> > > +++ b/arch/mips/include/asm/cpu-type.h
>> > > @@ -20,6 +20,10 @@ static inline int __pure __get_cpu_type(const int
>> > cpu_type)
>> > >       case CPU_LOONGSON2:
>> > >  #endif
>> > >
>> > > +#ifdef CONFIG_SYS_HAS_CPU_LOONGSON3
>> > > +     case CPU_LOONGSON3:
>> > > +#endif
>> > > +
>> > >  #ifdef CONFIG_SYS_HAS_CPU_LOONGSON1B
>> > >       case CPU_LOONGSON1:
>> > >  #endif
>> > > diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
>> > > index c814287..4bc81b2 100644
>> > > --- a/arch/mips/kernel/cpu-probe.c
>> > > +++ b/arch/mips/kernel/cpu-probe.c
>> > > @@ -639,17 +639,23 @@ static inline void cpu_probe_legacy(struct
>> > cpuinfo_mips *c, unsigned int cpu)
>> > >                            MIPS_CPU_LLSC;
>> > >               c->tlbsize = 64;
>> > >               break;
>> > > -     case PRID_IMP_LOONGSON2:
>> > > -             c->cputype = CPU_LOONGSON2;
>> > > -             __cpu_name[cpu] = "ICT Loongson-2";
>> > > -
>> > > +     case PRID_IMP_LOONGSON2: /* Loongson-2/3 have the same PRID_IMP
>> > field */
>> >
>> > What about renaming that as something like PRID_IMP_LOONGSON23 given
>> > it is for both Loongson 2 and 3?
>> >
>> Since Loongson-1 is 32-bit CPU and Loongson-2/3 are 64 bit, can I use
>> PRID_IMP_LOONGSON_32 and PRID_IMP_LOONGSON_64?
>> In my opinion these names are better.
>
> That would be the best I agree.
>
>> >
>> > >               switch (c->processor_id & PRID_REV_MASK) {
>> > >               case PRID_REV_LOONGSON2E:
>> > > +                     c->cputype = CPU_LOONGSON2;
>> > > +                     __cpu_name[cpu] = "ICT Loongson-2E";
>> > >                       set_elf_platform(cpu, "loongson2e");
>> > >                       break;
>> > >               case PRID_REV_LOONGSON2F:
>> > > +                     c->cputype = CPU_LOONGSON2;
>> > > +                     __cpu_name[cpu] = "ICT Loongson-2F";
>> > >                       set_elf_platform(cpu, "loongson2f");
>> > >                       break;
>> >
>> > As remarked by Aaro Koskinen, changing the names of the Loongson 2 CPUs
>> > (which is displayedd in /proc/cpuinfo) will break at least
>> > GCC -march=native option. The name should be left unchanged.
>> >
>> Can I keep it as is and then submit a patch to GCC? I think it is important
>> to distinguish 2E/2F/3A in cpuinfo.
>
> I think first the patch has to be integrated to GCC, and then you have
> to wait at least a few months so that people start using the new
> version. Then it should be possible to modify this.
>
> That said, other programs than GCC might use this information from
> /proc/cpuinfo and might also break with this change.
The GCC patch has been accepted yesterday, and the coming V17 patchset
won't be accept at least in kernel-3.14,
So, I'll keep the name in V17.

>
>> >
>> > > +             case PRID_REV_LOONGSON3A:
>> > > +                     c->cputype = CPU_LOONGSON3;
>> > > +                     __cpu_name[cpu] = "ICT Loongson-3A";
>> > > +                     set_elf_platform(cpu, "loongson3a");
>> > > +                     break;
>> > >               }
>> > >
>> > >               set_isa(c, MIPS_CPU_ISA_III);
>> > > diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
>> > > index 73f02da..cc02527 100644
>> > > --- a/arch/mips/mm/c-r4k.c
>> > > +++ b/arch/mips/mm/c-r4k.c
>> > > @@ -348,6 +348,7 @@ static inline void local_r4k___flush_cache_all(void
>> > * args)
>> > >  {
>> > >       switch (current_cpu_type()) {
>> > >       case CPU_LOONGSON2:
>> > > +     case CPU_LOONGSON3:
>> > >       case CPU_R4000SC:
>> > >       case CPU_R4000MC:
>> > >       case CPU_R4400SC:
>> > > @@ -1003,6 +1004,33 @@ static void probe_pcache(void)
>> > >               c->dcache.waybit = 0;
>> > >               break;
>> > >
>> > > +     case CPU_LOONGSON3:
>> > > +             config1 = read_c0_config1();
>> > > +             lsize = (config1 >> 19) & 7;
>> > > +             if (lsize)
>> > > +                     c->icache.linesz = 2 << lsize;
>> > > +             else
>> > > +                     c->icache.linesz = 0;
>> >
>> > Sorry to not have seen that before, but it can also be written as:
>> >
>> >         c->icache.linesz = lsize ? (2 << lsize) : 0;
>> >
>> > That said the current version is also fine, so as you prefer.
>> >
>> > > +             c->icache.sets = 64 << ((config1 >> 22) & 7);
>> > > +             c->icache.ways = 1 + ((config1 >> 16) & 7);
>> > > +             icache_size = c->icache.sets *
>> > > +                                       c->icache.ways *
>> > > +                                       c->icache.linesz;
>> > > +             c->icache.waybit = 0;
>> > > +
>> > > +             lsize = (config1 >> 10) & 7;
>> > > +             if (lsize)
>> > > +                     c->dcache.linesz = 2 << lsize;
>> > > +             else
>> > > +                     c->dcache.linesz = 0;
>> > > +             c->dcache.sets = 64 << ((config1 >> 13) & 7);
>> > > +             c->dcache.ways = 1 + ((config1 >> 7) & 7);
>> > > +             dcache_size = c->dcache.sets *
>> > > +                                       c->dcache.ways *
>> > > +                                       c->dcache.linesz;
>> > > +             c->dcache.waybit = 0;
>> > > +             break;
>> > > +
>> > >       default:
>> > >               if (!(config & MIPS_CONF_M))
>> > >                       panic("Don't know how to probe P-caches on this
>> > cpu.");
>> > > @@ -1222,6 +1250,33 @@ static void __init loongson2_sc_init(void)
>> > >       c->options |= MIPS_CPU_INCLUSIVE_CACHES;
>> > >  }
>> > >
>> > > +static void __init loongson3_sc_init(void)
>> > > +{
>> > > +     struct cpuinfo_mips *c = &current_cpu_data;
>> > > +     unsigned int config2, lsize;
>> > > +
>> > > +     config2 = read_c0_config2();
>> > > +     lsize = (config2 >> 4) & 15;
>> > > +     if (lsize)
>> > > +             c->scache.linesz = 2 << lsize;
>> > > +     else
>> > > +             c->scache.linesz = 0;
>> > > +     c->scache.sets = 64 << ((config2 >> 8) & 15);
>> > > +     c->scache.ways = 1 + (config2 & 15);
>> > > +
>> > > +     scache_size = c->scache.sets *
>> > > +                               c->scache.ways *
>> > > +                               c->scache.linesz;
>> > > +     /* Loongson-3 has 4 cores, 1MB scache for each. scaches are shared
>> > */
>> > > +     scache_size *= 4;
>> > > +     c->scache.waybit = 0;
>> > > +     pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
>> > > +            scache_size >> 10, way_string[c->scache.ways],
>> > c->scache.linesz);
>> > > +     if (scache_size)
>> > > +             c->options |= MIPS_CPU_INCLUSIVE_CACHES;
>> > > +     return;
>> > > +}
>> > > +
>> > >  extern int r5k_sc_init(void);
>> > >  extern int rm7k_sc_init(void);
>> > >  extern int mips_sc_init(void);
>> > > @@ -1274,6 +1329,10 @@ static void setup_scache(void)
>> > >               loongson2_sc_init();
>> > >               return;
>> > >
>> > > +     case CPU_LOONGSON3:
>> > > +             loongson3_sc_init();
>> > > +             return;
>> > > +
>> > >       case CPU_XLP:
>> > >               /* don't need to worry about L2, fully coherent */
>> > >               return;
>> > > diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
>> > > index da3b0b9..298f281 100644
>> > > --- a/arch/mips/mm/tlb-r4k.c
>> > > +++ b/arch/mips/mm/tlb-r4k.c
>> > > @@ -53,13 +53,14 @@ extern void build_tlb_refill_handler(void);
>> > >  #endif /* CONFIG_MIPS_MT_SMTC */
>> > >
>> > >  /*
>> > > - * LOONGSON2 has a 4 entry itlb which is a subset of dtlb,
>> > > - * unfortrunately, itlb is not totally transparent to software.
>> > > + * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb,
>> > > + * unfortunately, itlb is not totally transparent to software.
>> > >   */
>> > >  static inline void flush_itlb(void)
>> > >  {
>> > >       switch (current_cpu_type()) {
>> > >       case CPU_LOONGSON2:
>> > > +     case CPU_LOONGSON3:
>> > >               write_c0_diag(4);
>> > >               break;
>> > >       default:
>> > > diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
>> > > index 183f2b5..f89124c 100644
>> > > --- a/arch/mips/mm/tlbex.c
>> > > +++ b/arch/mips/mm/tlbex.c
>> > > @@ -579,6 +579,7 @@ static void build_tlb_write_entry(u32 **p, struct
>> > uasm_label **l,
>> > >       case CPU_BMIPS4380:
>> > >       case CPU_BMIPS5000:
>> > >       case CPU_LOONGSON2:
>> > > +     case CPU_LOONGSON3:
>> > >       case CPU_R5500:
>> > >               if (m4kc_tlbp_war())
>> > >                       uasm_i_nop(p);
>> > > --
>> > > 1.7.7.3
>> > >
>> > >
>> >
>> > --
>> > Aurelien Jarno                          GPG: 1024D/F1BCDB73
>> > aurelien@aurel32.net                 http://www.aurel32.net
>> >
>> >
>
> --
> Aurelien Jarno                          GPG: 1024D/F1BCDB73
> aurelien@aurel32.net                 http://www.aurel32.net
>

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

* Re: [PATCH V16 08/12] MIPS: Loongson: Add swiotlb to support big memory (>4GB)
  2014-01-11 15:25       ` Aurelien Jarno
@ 2014-01-12  9:12         ` Huacai Chen
  2014-01-12  9:57           ` Aurelien Jarno
  0 siblings, 1 reply; 55+ messages in thread
From: Huacai Chen @ 2014-01-12  9:12 UTC (permalink / raw)
  To: Aurelien Jarno
  Cc: Alex Smith, Ralf Baechle, John Crispin, Steven J. Hill,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Sat, Jan 11, 2014 at 11:25 PM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> On Sat, Jan 11, 2014 at 08:50:25PM +0800, Huacai Chen wrote:
>> On Thu, Jan 9, 2014 at 8:56 PM, Alex Smith <alex.smith@imgtec.com> wrote:
>>
>> > On 08/01/14 02:44, Huacai Chen wrote:
>> >
>> >> This is probably a workaround because Loongson doesn't support DMA
>> >> address above 4GB. If memory is more than 4GB, CONFIG_SWIOTLB and
>> >> ZONE_DMA32 should be selected. In this way, DMA pages are allocated
>> >> below 4GB preferably.
>> >>
>> >> However, CONFIG_SWIOTLB+ZONE_DMA32 is not enough, so, we provide a
>> >> platform-specific dma_map_ops::set_dma_mask() to make sure each
>> >> driver's dma_mask and coherent_dma_mask is below 32-bit.
>> >>
>> >> Signed-off-by: Huacai Chen <chenhc@lemote.com>
>> >> Signed-off-by: Hongliang Tao <taohl@lemote.com>
>> >> Signed-off-by: Hua Yan <yanh@lemote.com>
>> >> ---
>> >>   arch/mips/include/asm/dma-mapping.h                |    5 +
>> >>   .../mips/include/asm/mach-loongson/dma-coherence.h |   22 +++-
>> >>   arch/mips/loongson/common/Makefile                 |    5 +
>> >>   arch/mips/loongson/common/dma-swiotlb.c            |  165
>> >> ++++++++++++++++++++
>> >>   4 files changed, 196 insertions(+), 1 deletions(-)
>> >>   create mode 100644 arch/mips/loongson/common/dma-swiotlb.c
>> >>
>> >> diff --git a/arch/mips/include/asm/dma-mapping.h
>> >> b/arch/mips/include/asm/dma-mapping.h
>> >> index 84238c5..06412aa 100644
>> >> --- a/arch/mips/include/asm/dma-mapping.h
>> >> +++ b/arch/mips/include/asm/dma-mapping.h
>> >> @@ -49,9 +49,14 @@ static inline int dma_mapping_error(struct device
>> >> *dev, u64 mask)
>> >>   static inline int
>> >>   dma_set_mask(struct device *dev, u64 mask)
>> >>   {
>> >> +       struct dma_map_ops *ops = get_dma_ops(dev);
>> >> +
>> >>         if(!dev->dma_mask || !dma_supported(dev, mask))
>> >>                 return -EIO;
>> >>
>> >> +       if (ops->set_dma_mask)
>> >> +               return ops->set_dma_mask(dev, mask);
>> >> +
>> >>         *dev->dma_mask = mask;
>> >>
>> >>         return 0;
>> >> diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h
>> >> b/arch/mips/include/asm/mach-loongson/dma-coherence.h
>> >> index aeb2c05..6a90275 100644
>> >> --- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
>> >> +++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
>> >> @@ -11,24 +11,40 @@
>> >>   #ifndef __ASM_MACH_LOONGSON_DMA_COHERENCE_H
>> >>   #define __ASM_MACH_LOONGSON_DMA_COHERENCE_H
>> >>
>> >> +#ifdef CONFIG_SWIOTLB
>> >> +#include <linux/swiotlb.h>
>> >> +#endif
>> >> +
>> >>   struct device;
>> >>
>> >> +extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
>> >> +extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
>> >>   static inline dma_addr_t plat_map_dma_mem(struct device *dev, void
>> >> *addr,
>> >>                                           size_t size)
>> >>   {
>> >> +#ifdef CONFIG_CPU_LOONGSON3
>> >> +       return virt_to_phys(addr);
>> >> +#else
>> >>         return virt_to_phys(addr) | 0x80000000;
>> >> +#endif
>> >>   }
>> >>
>> >>   static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
>> >>                                                struct page *page)
>> >>   {
>> >> +#ifdef CONFIG_CPU_LOONGSON3
>> >> +       return page_to_phys(page);
>> >> +#else
>> >>         return page_to_phys(page) | 0x80000000;
>> >> +#endif
>> >>   }
>> >>
>> >>   static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
>> >>         dma_addr_t dma_addr)
>> >>   {
>> >> -#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
>> >> +#if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT)
>> >> +       return dma_addr;
>> >> +#elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
>> >>         return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr &
>> >> 0x0fffffff);
>> >>   #else
>> >>         return dma_addr & 0x7fffffff;
>> >> @@ -55,7 +71,11 @@ static inline int plat_dma_supported(struct device
>> >> *dev, u64 mask)
>> >>
>> >>   static inline int plat_device_is_coherent(struct device *dev)
>> >>   {
>> >> +#ifdef CONFIG_DMA_NONCOHERENT
>> >>         return 0;
>> >> +#else
>> >> +       return 1;
>> >> +#endif /* CONFIG_DMA_NONCOHERENT */
>> >>   }
>> >>
>> >>   #endif /* __ASM_MACH_LOONGSON_DMA_COHERENCE_H */
>> >> diff --git a/arch/mips/loongson/common/Makefile
>> >> b/arch/mips/loongson/common/Makefile
>> >> index 9e4484c..0bb9cc9 100644
>> >> --- a/arch/mips/loongson/common/Makefile
>> >> +++ b/arch/mips/loongson/common/Makefile
>> >> @@ -26,3 +26,8 @@ obj-$(CONFIG_CS5536) += cs5536/
>> >>   #
>> >>
>> >>   obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
>> >> +
>> >> +#
>> >> +# Big Memory (SWIOTLB) Support
>> >> +#
>> >> +obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o
>> >> diff --git a/arch/mips/loongson/common/dma-swiotlb.c
>> >> b/arch/mips/loongson/common/dma-swiotlb.c
>> >> new file mode 100644
>> >> index 0000000..9d5451b
>> >> --- /dev/null
>> >> +++ b/arch/mips/loongson/common/dma-swiotlb.c
>> >> @@ -0,0 +1,165 @@
>> >> +#include <linux/mm.h>
>> >> +#include <linux/init.h>
>> >> +#include <linux/dma-mapping.h>
>> >> +#include <linux/scatterlist.h>
>> >> +#include <linux/swiotlb.h>
>> >> +#include <linux/bootmem.h>
>> >> +
>> >> +#include <asm/bootinfo.h>
>> >> +#include <dma-coherence.h>
>> >> +
>> >> +static void *loongson_dma_alloc_coherent(struct device *dev, size_t
>> >> size,
>> >> +               dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs
>> >> *attrs)
>> >> +{
>> >> +       void *ret;
>> >> +
>> >> +       if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
>> >> +               return ret;
>> >> +
>> >> +       /* ignore region specifiers */
>> >> +       gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
>> >> +
>> >> +#ifdef CONFIG_ISA
>> >> +       if (dev == NULL)
>> >> +               gfp |= __GFP_DMA;
>> >> +       else
>> >> +#endif
>> >> +#ifdef CONFIG_ZONE_DMA
>> >> +       if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
>> >> +               gfp |= __GFP_DMA;
>> >> +       else
>> >> +#endif
>> >> +#ifdef CONFIG_ZONE_DMA32
>> >> +        /* Loongson-3 only support DMA in the memory below 4GB now */
>> >> +       if (dev->coherent_dma_mask < DMA_BIT_MASK(40))
>> >> +               gfp |= __GFP_DMA32;
>> >> +       else
>> >> +#endif
>> >> +       ;
>> >> +       gfp |= __GFP_NORETRY;
>> >> +
>> >> +       ret = swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
>> >> +       mb();
>> >> +       return ret;
>> >> +}
>> >> +
>> >> +static void loongson_dma_free_coherent(struct device *dev, size_t size,
>> >> +               void *vaddr, dma_addr_t dma_handle, struct dma_attrs
>> >> *attrs)
>> >> +{
>> >> +       int order = get_order(size);
>> >> +
>> >> +       if (dma_release_from_coherent(dev, order, vaddr))
>> >> +               return;
>> >> +
>> >> +       swiotlb_free_coherent(dev, size, vaddr, dma_handle);
>> >> +}
>> >> +
>> >> +static dma_addr_t loongson_dma_map_page(struct device *dev, struct page
>> >> *page,
>> >> +                               unsigned long offset, size_t size,
>> >> +                               enum dma_data_direction dir,
>> >> +                               struct dma_attrs *attrs)
>> >> +{
>> >> +       dma_addr_t daddr = swiotlb_map_page(dev, page, offset, size,
>> >> +                                       dir, attrs);
>> >> +       mb();
>> >> +       return daddr;
>> >> +}
>> >> +
>> >> +static int loongson_dma_map_sg(struct device *dev, struct scatterlist
>> >> *sg,
>> >> +                               int nents, enum dma_data_direction dir,
>> >> +                               struct dma_attrs *attrs)
>> >> +{
>> >> +       int r = swiotlb_map_sg_attrs(dev, sg, nents, dir, NULL);
>> >> +       mb();
>> >> +
>> >> +       return r;
>> >> +}
>> >> +
>> >> +static void loongson_dma_sync_single_for_device(struct device *dev,
>> >> +                               dma_addr_t dma_handle, size_t size,
>> >> +                               enum dma_data_direction dir)
>> >> +{
>> >> +       swiotlb_sync_single_for_device(dev, dma_handle, size, dir);
>> >> +       mb();
>> >> +}
>> >> +
>> >> +static void loongson_dma_sync_sg_for_device(struct device *dev,
>> >> +                               struct scatterlist *sg, int nents,
>> >> +                               enum dma_data_direction dir)
>> >> +{
>> >> +       swiotlb_sync_sg_for_device(dev, sg, nents, dir);
>> >> +       mb();
>> >> +}
>> >> +
>> >> +static dma_addr_t
>> >> +loongson_unity_phys_to_dma(struct device *dev, phys_addr_t paddr)
>> >> +{
>> >> +       return paddr;
>> >> +}
>> >> +
>> >> +static phys_addr_t
>> >> +loongson_unity_dma_to_phys(struct device *dev, dma_addr_t daddr)
>> >> +{
>> >> +       return daddr;
>> >> +}
>> >> +
>> >> +struct loongson_dma_map_ops {
>> >> +       struct dma_map_ops dma_map_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);
>> >> +};
>> >> +
>> >> +dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
>> >> +{
>> >> +       struct loongson_dma_map_ops *ops = container_of(get_dma_ops(dev),
>> >> +                               struct loongson_dma_map_ops, dma_map_ops);
>> >> +
>> >> +       return ops->phys_to_dma(dev, paddr);
>> >> +}
>> >> +
>> >> +phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
>> >> +{
>> >> +       struct loongson_dma_map_ops *ops = container_of(get_dma_ops(dev),
>> >> +                               struct loongson_dma_map_ops, dma_map_ops);
>> >> +
>> >> +       return ops->dma_to_phys(dev, daddr);
>> >> +}
>> >>
>> >
>> > This seems a little bit convoluted. Since phys_to_dma and dma_to_phys will
>> > always end up calling the loongson_unity_ functions, I don't see any point
>> > in having the loongson_dma_map_ops structure to point to them. You can just
>> > implement phys_to_dma and dma_to_phys as inlines in
>> > mach-loongson/dma-coherence.h.
>> >
>> This part comes from arch/mips/cavium-octeon/dma-octeon.c, I think this is
>> needed in future.
>
> On Cavium Octeon you have different mappings depending on the CPU, but
> this is not the case on Loongson 3A. So I think that Alex is right and
> that it can be simplified.
Loongson-3 can work with other northbridge (LS2H) other than RS780 and
there are already products.
Loongson-3 with LS2H has different mappings than RS780 (but of course
the current patchset doesn't
support LS2H). Can I keep the code as is? Or I must take Alex's
suggestion and modify here until the
LS2H patchset?

>
> --
> Aurelien Jarno                          GPG: 1024D/F1BCDB73
> aurelien@aurel32.net                 http://www.aurel32.net
>

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

* Re: [PATCH V16 02/12] MIPS: Loongson: Add basic Loongson-3 CPU support
  2014-01-12  9:03         ` Huacai Chen
@ 2014-01-12  9:57           ` Aurelien Jarno
  2014-01-12 12:10             ` Aaro Koskinen
  0 siblings, 1 reply; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-12  9:57 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan, Aaro Koskinen

On Sun, Jan 12, 2014 at 05:03:51PM +0800, Huacai Chen wrote:
> On Fri, Jan 10, 2014 at 5:36 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> > On Thu, Jan 09, 2014 at 04:30:54PM +0800, Huacai Chen wrote:
> >> On Thu, Jan 9, 2014 at 3:58 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> >>
> >> > On Wed, Jan 08, 2014 at 10:44:18AM +0800, Huacai Chen wrote:
> >> > > Basic Loongson-3 CPU support include CPU probing and TLB/cache
> >> > > initializing.
> >> > >
> >> > > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> >> > > Signed-off-by: Hongliang Tao <taohl@lemote.com>
> >> > > Signed-off-by: Hua Yan <yanh@lemote.com>
> >> > > ---
> >> > >  arch/mips/include/asm/cpu-type.h |    4 ++
> >> > >  arch/mips/kernel/cpu-probe.c     |   14 ++++++--
> >> > >  arch/mips/mm/c-r4k.c             |   59
> >> > ++++++++++++++++++++++++++++++++++++++
> >> > >  arch/mips/mm/tlb-r4k.c           |    5 ++-
> >> > >  arch/mips/mm/tlbex.c             |    1 +
> >> > >  5 files changed, 77 insertions(+), 6 deletions(-)
> >> > >
> >> > > diff --git a/arch/mips/include/asm/cpu-type.h
> >> > b/arch/mips/include/asm/cpu-type.h
> >> > > index 4a402cc..a591e63 100644
> >> > > --- a/arch/mips/include/asm/cpu-type.h
> >> > > +++ b/arch/mips/include/asm/cpu-type.h
> >> > > @@ -20,6 +20,10 @@ static inline int __pure __get_cpu_type(const int
> >> > cpu_type)
> >> > >       case CPU_LOONGSON2:
> >> > >  #endif
> >> > >
> >> > > +#ifdef CONFIG_SYS_HAS_CPU_LOONGSON3
> >> > > +     case CPU_LOONGSON3:
> >> > > +#endif
> >> > > +
> >> > >  #ifdef CONFIG_SYS_HAS_CPU_LOONGSON1B
> >> > >       case CPU_LOONGSON1:
> >> > >  #endif
> >> > > diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> >> > > index c814287..4bc81b2 100644
> >> > > --- a/arch/mips/kernel/cpu-probe.c
> >> > > +++ b/arch/mips/kernel/cpu-probe.c
> >> > > @@ -639,17 +639,23 @@ static inline void cpu_probe_legacy(struct
> >> > cpuinfo_mips *c, unsigned int cpu)
> >> > >                            MIPS_CPU_LLSC;
> >> > >               c->tlbsize = 64;
> >> > >               break;
> >> > > -     case PRID_IMP_LOONGSON2:
> >> > > -             c->cputype = CPU_LOONGSON2;
> >> > > -             __cpu_name[cpu] = "ICT Loongson-2";
> >> > > -
> >> > > +     case PRID_IMP_LOONGSON2: /* Loongson-2/3 have the same PRID_IMP
> >> > field */
> >> >
> >> > What about renaming that as something like PRID_IMP_LOONGSON23 given
> >> > it is for both Loongson 2 and 3?
> >> >
> >> Since Loongson-1 is 32-bit CPU and Loongson-2/3 are 64 bit, can I use
> >> PRID_IMP_LOONGSON_32 and PRID_IMP_LOONGSON_64?
> >> In my opinion these names are better.
> >
> > That would be the best I agree.
> >
> >> >
> >> > >               switch (c->processor_id & PRID_REV_MASK) {
> >> > >               case PRID_REV_LOONGSON2E:
> >> > > +                     c->cputype = CPU_LOONGSON2;
> >> > > +                     __cpu_name[cpu] = "ICT Loongson-2E";
> >> > >                       set_elf_platform(cpu, "loongson2e");
> >> > >                       break;
> >> > >               case PRID_REV_LOONGSON2F:
> >> > > +                     c->cputype = CPU_LOONGSON2;
> >> > > +                     __cpu_name[cpu] = "ICT Loongson-2F";
> >> > >                       set_elf_platform(cpu, "loongson2f");
> >> > >                       break;
> >> >
> >> > As remarked by Aaro Koskinen, changing the names of the Loongson 2 CPUs
> >> > (which is displayedd in /proc/cpuinfo) will break at least
> >> > GCC -march=native option. The name should be left unchanged.
> >> >
> >> Can I keep it as is and then submit a patch to GCC? I think it is important
> >> to distinguish 2E/2F/3A in cpuinfo.
> >
> > I think first the patch has to be integrated to GCC, and then you have
> > to wait at least a few months so that people start using the new
> > version. Then it should be possible to modify this.
> >
> > That said, other programs than GCC might use this information from
> > /proc/cpuinfo and might also break with this change.
> The GCC patch has been accepted yesterday, and the coming V17 patchset
> won't be accept at least in kernel-3.14,
> So, I'll keep the name in V17.

Kernel 3.15 is expected in roughly 6 months, it might still be a bit
tight for the change to propagate, even if I have seen it has been added
to the 4.8 branch. What the others things? Aaro?

Aurelien

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 08/12] MIPS: Loongson: Add swiotlb to support big memory (>4GB)
  2014-01-12  9:12         ` Huacai Chen
@ 2014-01-12  9:57           ` Aurelien Jarno
  0 siblings, 0 replies; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-12  9:57 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Alex Smith, Ralf Baechle, John Crispin, Steven J. Hill,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Sun, Jan 12, 2014 at 05:12:46PM +0800, Huacai Chen wrote:
> On Sat, Jan 11, 2014 at 11:25 PM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> > On Sat, Jan 11, 2014 at 08:50:25PM +0800, Huacai Chen wrote:
> >> On Thu, Jan 9, 2014 at 8:56 PM, Alex Smith <alex.smith@imgtec.com> wrote:
> >>
> >> > On 08/01/14 02:44, Huacai Chen wrote:
> >> >
> >> >> This is probably a workaround because Loongson doesn't support DMA
> >> >> address above 4GB. If memory is more than 4GB, CONFIG_SWIOTLB and
> >> >> ZONE_DMA32 should be selected. In this way, DMA pages are allocated
> >> >> below 4GB preferably.
> >> >>
> >> >> However, CONFIG_SWIOTLB+ZONE_DMA32 is not enough, so, we provide a
> >> >> platform-specific dma_map_ops::set_dma_mask() to make sure each
> >> >> driver's dma_mask and coherent_dma_mask is below 32-bit.
> >> >>
> >> >> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> >> >> Signed-off-by: Hongliang Tao <taohl@lemote.com>
> >> >> Signed-off-by: Hua Yan <yanh@lemote.com>
> >> >> ---
> >> >>   arch/mips/include/asm/dma-mapping.h                |    5 +
> >> >>   .../mips/include/asm/mach-loongson/dma-coherence.h |   22 +++-
> >> >>   arch/mips/loongson/common/Makefile                 |    5 +
> >> >>   arch/mips/loongson/common/dma-swiotlb.c            |  165
> >> >> ++++++++++++++++++++
> >> >>   4 files changed, 196 insertions(+), 1 deletions(-)
> >> >>   create mode 100644 arch/mips/loongson/common/dma-swiotlb.c
> >> >>
> >> >> diff --git a/arch/mips/include/asm/dma-mapping.h
> >> >> b/arch/mips/include/asm/dma-mapping.h
> >> >> index 84238c5..06412aa 100644
> >> >> --- a/arch/mips/include/asm/dma-mapping.h
> >> >> +++ b/arch/mips/include/asm/dma-mapping.h
> >> >> @@ -49,9 +49,14 @@ static inline int dma_mapping_error(struct device
> >> >> *dev, u64 mask)
> >> >>   static inline int
> >> >>   dma_set_mask(struct device *dev, u64 mask)
> >> >>   {
> >> >> +       struct dma_map_ops *ops = get_dma_ops(dev);
> >> >> +
> >> >>         if(!dev->dma_mask || !dma_supported(dev, mask))
> >> >>                 return -EIO;
> >> >>
> >> >> +       if (ops->set_dma_mask)
> >> >> +               return ops->set_dma_mask(dev, mask);
> >> >> +
> >> >>         *dev->dma_mask = mask;
> >> >>
> >> >>         return 0;
> >> >> diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h
> >> >> b/arch/mips/include/asm/mach-loongson/dma-coherence.h
> >> >> index aeb2c05..6a90275 100644
> >> >> --- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
> >> >> +++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
> >> >> @@ -11,24 +11,40 @@
> >> >>   #ifndef __ASM_MACH_LOONGSON_DMA_COHERENCE_H
> >> >>   #define __ASM_MACH_LOONGSON_DMA_COHERENCE_H
> >> >>
> >> >> +#ifdef CONFIG_SWIOTLB
> >> >> +#include <linux/swiotlb.h>
> >> >> +#endif
> >> >> +
> >> >>   struct device;
> >> >>
> >> >> +extern dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
> >> >> +extern phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
> >> >>   static inline dma_addr_t plat_map_dma_mem(struct device *dev, void
> >> >> *addr,
> >> >>                                           size_t size)
> >> >>   {
> >> >> +#ifdef CONFIG_CPU_LOONGSON3
> >> >> +       return virt_to_phys(addr);
> >> >> +#else
> >> >>         return virt_to_phys(addr) | 0x80000000;
> >> >> +#endif
> >> >>   }
> >> >>
> >> >>   static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
> >> >>                                                struct page *page)
> >> >>   {
> >> >> +#ifdef CONFIG_CPU_LOONGSON3
> >> >> +       return page_to_phys(page);
> >> >> +#else
> >> >>         return page_to_phys(page) | 0x80000000;
> >> >> +#endif
> >> >>   }
> >> >>
> >> >>   static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
> >> >>         dma_addr_t dma_addr)
> >> >>   {
> >> >> -#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
> >> >> +#if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT)
> >> >> +       return dma_addr;
> >> >> +#elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
> >> >>         return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr &
> >> >> 0x0fffffff);
> >> >>   #else
> >> >>         return dma_addr & 0x7fffffff;
> >> >> @@ -55,7 +71,11 @@ static inline int plat_dma_supported(struct device
> >> >> *dev, u64 mask)
> >> >>
> >> >>   static inline int plat_device_is_coherent(struct device *dev)
> >> >>   {
> >> >> +#ifdef CONFIG_DMA_NONCOHERENT
> >> >>         return 0;
> >> >> +#else
> >> >> +       return 1;
> >> >> +#endif /* CONFIG_DMA_NONCOHERENT */
> >> >>   }
> >> >>
> >> >>   #endif /* __ASM_MACH_LOONGSON_DMA_COHERENCE_H */
> >> >> diff --git a/arch/mips/loongson/common/Makefile
> >> >> b/arch/mips/loongson/common/Makefile
> >> >> index 9e4484c..0bb9cc9 100644
> >> >> --- a/arch/mips/loongson/common/Makefile
> >> >> +++ b/arch/mips/loongson/common/Makefile
> >> >> @@ -26,3 +26,8 @@ obj-$(CONFIG_CS5536) += cs5536/
> >> >>   #
> >> >>
> >> >>   obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
> >> >> +
> >> >> +#
> >> >> +# Big Memory (SWIOTLB) Support
> >> >> +#
> >> >> +obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o
> >> >> diff --git a/arch/mips/loongson/common/dma-swiotlb.c
> >> >> b/arch/mips/loongson/common/dma-swiotlb.c
> >> >> new file mode 100644
> >> >> index 0000000..9d5451b
> >> >> --- /dev/null
> >> >> +++ b/arch/mips/loongson/common/dma-swiotlb.c
> >> >> @@ -0,0 +1,165 @@
> >> >> +#include <linux/mm.h>
> >> >> +#include <linux/init.h>
> >> >> +#include <linux/dma-mapping.h>
> >> >> +#include <linux/scatterlist.h>
> >> >> +#include <linux/swiotlb.h>
> >> >> +#include <linux/bootmem.h>
> >> >> +
> >> >> +#include <asm/bootinfo.h>
> >> >> +#include <dma-coherence.h>
> >> >> +
> >> >> +static void *loongson_dma_alloc_coherent(struct device *dev, size_t
> >> >> size,
> >> >> +               dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs
> >> >> *attrs)
> >> >> +{
> >> >> +       void *ret;
> >> >> +
> >> >> +       if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
> >> >> +               return ret;
> >> >> +
> >> >> +       /* ignore region specifiers */
> >> >> +       gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
> >> >> +
> >> >> +#ifdef CONFIG_ISA
> >> >> +       if (dev == NULL)
> >> >> +               gfp |= __GFP_DMA;
> >> >> +       else
> >> >> +#endif
> >> >> +#ifdef CONFIG_ZONE_DMA
> >> >> +       if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
> >> >> +               gfp |= __GFP_DMA;
> >> >> +       else
> >> >> +#endif
> >> >> +#ifdef CONFIG_ZONE_DMA32
> >> >> +        /* Loongson-3 only support DMA in the memory below 4GB now */
> >> >> +       if (dev->coherent_dma_mask < DMA_BIT_MASK(40))
> >> >> +               gfp |= __GFP_DMA32;
> >> >> +       else
> >> >> +#endif
> >> >> +       ;
> >> >> +       gfp |= __GFP_NORETRY;
> >> >> +
> >> >> +       ret = swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
> >> >> +       mb();
> >> >> +       return ret;
> >> >> +}
> >> >> +
> >> >> +static void loongson_dma_free_coherent(struct device *dev, size_t size,
> >> >> +               void *vaddr, dma_addr_t dma_handle, struct dma_attrs
> >> >> *attrs)
> >> >> +{
> >> >> +       int order = get_order(size);
> >> >> +
> >> >> +       if (dma_release_from_coherent(dev, order, vaddr))
> >> >> +               return;
> >> >> +
> >> >> +       swiotlb_free_coherent(dev, size, vaddr, dma_handle);
> >> >> +}
> >> >> +
> >> >> +static dma_addr_t loongson_dma_map_page(struct device *dev, struct page
> >> >> *page,
> >> >> +                               unsigned long offset, size_t size,
> >> >> +                               enum dma_data_direction dir,
> >> >> +                               struct dma_attrs *attrs)
> >> >> +{
> >> >> +       dma_addr_t daddr = swiotlb_map_page(dev, page, offset, size,
> >> >> +                                       dir, attrs);
> >> >> +       mb();
> >> >> +       return daddr;
> >> >> +}
> >> >> +
> >> >> +static int loongson_dma_map_sg(struct device *dev, struct scatterlist
> >> >> *sg,
> >> >> +                               int nents, enum dma_data_direction dir,
> >> >> +                               struct dma_attrs *attrs)
> >> >> +{
> >> >> +       int r = swiotlb_map_sg_attrs(dev, sg, nents, dir, NULL);
> >> >> +       mb();
> >> >> +
> >> >> +       return r;
> >> >> +}
> >> >> +
> >> >> +static void loongson_dma_sync_single_for_device(struct device *dev,
> >> >> +                               dma_addr_t dma_handle, size_t size,
> >> >> +                               enum dma_data_direction dir)
> >> >> +{
> >> >> +       swiotlb_sync_single_for_device(dev, dma_handle, size, dir);
> >> >> +       mb();
> >> >> +}
> >> >> +
> >> >> +static void loongson_dma_sync_sg_for_device(struct device *dev,
> >> >> +                               struct scatterlist *sg, int nents,
> >> >> +                               enum dma_data_direction dir)
> >> >> +{
> >> >> +       swiotlb_sync_sg_for_device(dev, sg, nents, dir);
> >> >> +       mb();
> >> >> +}
> >> >> +
> >> >> +static dma_addr_t
> >> >> +loongson_unity_phys_to_dma(struct device *dev, phys_addr_t paddr)
> >> >> +{
> >> >> +       return paddr;
> >> >> +}
> >> >> +
> >> >> +static phys_addr_t
> >> >> +loongson_unity_dma_to_phys(struct device *dev, dma_addr_t daddr)
> >> >> +{
> >> >> +       return daddr;
> >> >> +}
> >> >> +
> >> >> +struct loongson_dma_map_ops {
> >> >> +       struct dma_map_ops dma_map_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);
> >> >> +};
> >> >> +
> >> >> +dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
> >> >> +{
> >> >> +       struct loongson_dma_map_ops *ops = container_of(get_dma_ops(dev),
> >> >> +                               struct loongson_dma_map_ops, dma_map_ops);
> >> >> +
> >> >> +       return ops->phys_to_dma(dev, paddr);
> >> >> +}
> >> >> +
> >> >> +phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
> >> >> +{
> >> >> +       struct loongson_dma_map_ops *ops = container_of(get_dma_ops(dev),
> >> >> +                               struct loongson_dma_map_ops, dma_map_ops);
> >> >> +
> >> >> +       return ops->dma_to_phys(dev, daddr);
> >> >> +}
> >> >>
> >> >
> >> > This seems a little bit convoluted. Since phys_to_dma and dma_to_phys will
> >> > always end up calling the loongson_unity_ functions, I don't see any point
> >> > in having the loongson_dma_map_ops structure to point to them. You can just
> >> > implement phys_to_dma and dma_to_phys as inlines in
> >> > mach-loongson/dma-coherence.h.
> >> >
> >> This part comes from arch/mips/cavium-octeon/dma-octeon.c, I think this is
> >> needed in future.
> >
> > On Cavium Octeon you have different mappings depending on the CPU, but
> > this is not the case on Loongson 3A. So I think that Alex is right and
> > that it can be simplified.
> Loongson-3 can work with other northbridge (LS2H) other than RS780 and
> there are already products.
> Loongson-3 with LS2H has different mappings than RS780 (but of course
> the current patchset doesn't
> support LS2H). Can I keep the code as is? Or I must take Alex's
> suggestion and modify here until the
> LS2H patchset?

I think it's better to use simple code as Alex suggested, and to change
it later in the LS2H patchset.

Aurelien

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 02/12] MIPS: Loongson: Add basic Loongson-3 CPU support
  2014-01-12  9:57           ` Aurelien Jarno
@ 2014-01-12 12:10             ` Aaro Koskinen
  2014-01-18  1:54               ` John Crispin
  0 siblings, 1 reply; 55+ messages in thread
From: Aaro Koskinen @ 2014-01-12 12:10 UTC (permalink / raw)
  To: Aurelien Jarno, Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, linux-mips,
	Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

Hi,

On Sun, Jan 12, 2014 at 10:57:52AM +0100, Aurelien Jarno wrote:
> On Sun, Jan 12, 2014 at 05:03:51PM +0800, Huacai Chen wrote:
> > On Fri, Jan 10, 2014 at 5:36 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> > > On Thu, Jan 09, 2014 at 04:30:54PM +0800, Huacai Chen wrote:
> > >> On Thu, Jan 9, 2014 at 3:58 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> > >>
> > >> > On Wed, Jan 08, 2014 at 10:44:18AM +0800, Huacai Chen wrote:
> > >> > > Basic Loongson-3 CPU support include CPU probing and TLB/cache
> > >> > > initializing.
> > >> > >
> > >> > > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > >> > > Signed-off-by: Hongliang Tao <taohl@lemote.com>
> > >> > > Signed-off-by: Hua Yan <yanh@lemote.com>
> > >> > > ---
> > >> > >  arch/mips/include/asm/cpu-type.h |    4 ++
> > >> > >  arch/mips/kernel/cpu-probe.c     |   14 ++++++--
> > >> > >  arch/mips/mm/c-r4k.c             |   59
> > >> > ++++++++++++++++++++++++++++++++++++++
> > >> > >  arch/mips/mm/tlb-r4k.c           |    5 ++-
> > >> > >  arch/mips/mm/tlbex.c             |    1 +
> > >> > >  5 files changed, 77 insertions(+), 6 deletions(-)
> > >> > >
> > >> > > diff --git a/arch/mips/include/asm/cpu-type.h
> > >> > b/arch/mips/include/asm/cpu-type.h
> > >> > > index 4a402cc..a591e63 100644
> > >> > > --- a/arch/mips/include/asm/cpu-type.h
> > >> > > +++ b/arch/mips/include/asm/cpu-type.h
> > >> > > @@ -20,6 +20,10 @@ static inline int __pure __get_cpu_type(const int
> > >> > cpu_type)
> > >> > >       case CPU_LOONGSON2:
> > >> > >  #endif
> > >> > >
> > >> > > +#ifdef CONFIG_SYS_HAS_CPU_LOONGSON3
> > >> > > +     case CPU_LOONGSON3:
> > >> > > +#endif
> > >> > > +
> > >> > >  #ifdef CONFIG_SYS_HAS_CPU_LOONGSON1B
> > >> > >       case CPU_LOONGSON1:
> > >> > >  #endif
> > >> > > diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> > >> > > index c814287..4bc81b2 100644
> > >> > > --- a/arch/mips/kernel/cpu-probe.c
> > >> > > +++ b/arch/mips/kernel/cpu-probe.c
> > >> > > @@ -639,17 +639,23 @@ static inline void cpu_probe_legacy(struct
> > >> > cpuinfo_mips *c, unsigned int cpu)
> > >> > >                            MIPS_CPU_LLSC;
> > >> > >               c->tlbsize = 64;
> > >> > >               break;
> > >> > > -     case PRID_IMP_LOONGSON2:
> > >> > > -             c->cputype = CPU_LOONGSON2;
> > >> > > -             __cpu_name[cpu] = "ICT Loongson-2";
> > >> > > -
> > >> > > +     case PRID_IMP_LOONGSON2: /* Loongson-2/3 have the same PRID_IMP
> > >> > field */
> > >> >
> > >> > What about renaming that as something like PRID_IMP_LOONGSON23 given
> > >> > it is for both Loongson 2 and 3?
> > >> >
> > >> Since Loongson-1 is 32-bit CPU and Loongson-2/3 are 64 bit, can I use
> > >> PRID_IMP_LOONGSON_32 and PRID_IMP_LOONGSON_64?
> > >> In my opinion these names are better.
> > >
> > > That would be the best I agree.
> > >
> > >> >
> > >> > >               switch (c->processor_id & PRID_REV_MASK) {
> > >> > >               case PRID_REV_LOONGSON2E:
> > >> > > +                     c->cputype = CPU_LOONGSON2;
> > >> > > +                     __cpu_name[cpu] = "ICT Loongson-2E";
> > >> > >                       set_elf_platform(cpu, "loongson2e");
> > >> > >                       break;
> > >> > >               case PRID_REV_LOONGSON2F:
> > >> > > +                     c->cputype = CPU_LOONGSON2;
> > >> > > +                     __cpu_name[cpu] = "ICT Loongson-2F";
> > >> > >                       set_elf_platform(cpu, "loongson2f");
> > >> > >                       break;
> > >> >
> > >> > As remarked by Aaro Koskinen, changing the names of the Loongson 2 CPUs
> > >> > (which is displayedd in /proc/cpuinfo) will break at least
> > >> > GCC -march=native option. The name should be left unchanged.
> > >> >
> > >> Can I keep it as is and then submit a patch to GCC? I think it is important
> > >> to distinguish 2E/2F/3A in cpuinfo.
> > >
> > > I think first the patch has to be integrated to GCC, and then you have
> > > to wait at least a few months so that people start using the new
> > > version. Then it should be possible to modify this.
> > >
> > > That said, other programs than GCC might use this information from
> > > /proc/cpuinfo and might also break with this change.
> > The GCC patch has been accepted yesterday, and the coming V17 patchset
> > won't be accept at least in kernel-3.14,
> > So, I'll keep the name in V17.
> 
> Kernel 3.15 is expected in roughly 6 months, it might still be a bit
> tight for the change to propagate, even if I have seen it has been added
> to the 4.8 branch. What the others things? Aaro?

It doesn't really matter if some future version of GCC supports the
new name. Most people will continue to use older toolchains for years,
and we shouldn't change the behaviour of those.

A.

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

* Re: [PATCH V16 09/12] MIPS: Loongson: Add Loongson-3 Kconfig options
  2014-01-11 15:24     ` Aurelien Jarno
@ 2014-01-13  3:02       ` Huacai Chen
  2014-01-13  4:30         ` Aurelien Jarno
  0 siblings, 1 reply; 55+ messages in thread
From: Huacai Chen @ 2014-01-13  3:02 UTC (permalink / raw)
  To: Aurelien Jarno
  Cc: Alex Smith, Ralf Baechle, John Crispin, Steven J. Hill,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Sat, Jan 11, 2014 at 11:24 PM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> On Thu, Jan 09, 2014 at 01:07:30PM +0000, Alex Smith wrote:
>> On 08/01/14 02:44, Huacai Chen wrote:
>> >Added Kconfig options include: Loongson-3 CPU and machine definition,
>> >CPU cache features, UEFI-like firmware interface (LEFI), HT-linked PCI,
>> >and big memory support.
>> >
>> >Signed-off-by: Huacai Chen <chenhc@lemote.com>
>> >Signed-off-by: Hongliang Tao <taohl@lemote.com>
>> >Signed-off-by: Hua Yan <yanh@lemote.com>
>> >---
>> >  arch/mips/Kconfig           |   29 +++++++++++++++++++++++++++-
>> >  arch/mips/loongson/Kconfig  |   44 +++++++++++++++++++++++++++++++++++++++++++
>> >  arch/mips/loongson/Platform |    1 +
>> >  3 files changed, 73 insertions(+), 1 deletions(-)
>> >
>> >diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
>> >index 17cc7ff..513e941 100644
>> >--- a/arch/mips/Kconfig
>> >+++ b/arch/mips/Kconfig
>> >@@ -1487,6 +1487,18 @@ config CPU_LOONGSON2
>> >     select CPU_SUPPORTS_HIGHMEM
>> >     select CPU_SUPPORTS_HUGEPAGES
>> >
>> >+config CPU_LOONGSON3
>> >+    bool "Loongson 3 CPU"
>> >+    depends on SYS_HAS_CPU_LOONGSON3
>> >+    select CPU_SUPPORTS_64BIT_KERNEL
>> >+    select CPU_SUPPORTS_HIGHMEM
>> >+    select CPU_SUPPORTS_HUGEPAGES
>> >+    select WEAK_ORDERING
>> >+    select WEAK_REORDERING_BEYOND_LLSC
>> >+    help
>> >+            The Loongson 3 processor implements the MIPS III instruction set
>> >+            with many extensions.
>> >+
>>
>> This should be moved into the "CPU type" choice block. Currently
>> this appears as an option outside of that choice, and so it is
>> possible to build a kernel without any CPU type selected.
>>
>> Also, as Aurelien said on the previous version, shouldn't the
>> comment be changed to MIPS64R2 rather than MIPS III even if you
>> aren't selecting the MIPS64 CPU types for the time being? Note, if
>> you replied to that comment I may not have seen it - I think the
>> list is filtering your replies because they're HTML emails.
>>
>> >  config CPU_LOONGSON1
>> >     bool
>> >     select CPU_MIPS32
>> >@@ -1513,6 +1526,10 @@ config SYS_HAS_CPU_LOONGSON2F
>> >     select CPU_SUPPORTS_ADDRWINCFG if 64BIT
>> >     select CPU_SUPPORTS_UNCACHED_ACCELERATED
>> >
>> >+config SYS_HAS_CPU_LOONGSON3
>> >+    bool
>> >+    select CPU_SUPPORTS_CPUFREQ
>> >+
>> >  config SYS_HAS_CPU_LOONGSON1B
>> >     bool
>> >
>> >@@ -1703,7 +1720,7 @@ choice
>> >
>> >  config PAGE_SIZE_4KB
>> >     bool "4kB"
>> >-    depends on !CPU_LOONGSON2
>> >+    depends on !CPU_LOONGSON2 && !CPU_LOONGSON3
>> >     help
>> >      This option select the standard 4kB Linux page size.  On some
>> >      R3000-family processors this is the only available page size.  Using
>> >@@ -2373,6 +2390,16 @@ config PCI
>> >       your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
>> >       say Y, otherwise N.
>> >
>> >+config HT_PCI
>> >+    bool "Support for HT-linked PCI"
>> >+    depends on CPU_LOONGSON3
>> >+    select PCI_DOMAINS
>> >+    help
>> >+      Loongson family machines use Hyper-Transport bus for inter-core
>> >+      connection and device connection. The PCI bus is a subordinate
>> >+      linked at HT. Choose Y unless you are using Loongson 2E/2F based
>> >+      machines.
>> >+
>>
>> Should this default to y, given that it is selected in the
>> defconfig? Also, the comment referring to 2E/2F is redundant given
>> that it depends on CPU_LOONGSON3 and cannot be selected on those
>> machines.
>
> I am still not sure we need such an option. This option only changes an
> address in arch/mips/include/asm/mach-loongson/loongson.h:
>
> | #if defined(CONFIG_HT_PCI)
> | #define LOONGSON_PCIIO_BASE     loongson_sysconf.pci_io_base
> | #else
> | #define LOONGSON_PCIIO_BASE     0x1fd00000
> | #endif
>
> If both options are working on a Loongson 3 machine, it's definitely a
> good idea to leave the choice to the user. That said if only the address
> from loongson_sysconf.pci_io_base works on a Loongson 3 machine, this
> option must always be selected and is therefore useless.
HT_PCI is needed, because Loongson-3 device structure looks like this:
Loongson3-Core -----       ---- MEM
         |--- Cache ---|
HT1-controller  -------       ---- PCI-Controller --- PCI-Devices (PATH-B)
    |
    |
 PCI-Controller
    |
    |
 PCI-Devices (PATH-A)

If PCI devices are linked via PATH-A, we should select HT_PCI;
otherwise we should unselected HT_PCI.

>
>> >  config PCI_DOMAINS
>> >     bool
>> >
>> >diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
>> >index 263beb9..4f3967c 100644
>> >--- a/arch/mips/loongson/Kconfig
>> >+++ b/arch/mips/loongson/Kconfig
>> >@@ -59,6 +59,33 @@ config LEMOTE_MACH2F
>> >
>> >       These family machines include fuloong2f mini PC, yeeloong2f notebook,
>> >       LingLoong allinone PC and so forth.
>> >+
>> >+config LEMOTE_MACH3A
>> >+    bool "Lemote Loongson 3A family machines"
>> >+    select ARCH_SPARSEMEM_ENABLE
>> >+    select GENERIC_ISA_DMA_SUPPORT_BROKEN
>> >+    select GENERIC_HARDIRQS_NO__DO_IRQ
>> >+    select BOOT_ELF32
>> >+    select BOARD_SCACHE
>> >+    select CSRC_R4K
>> >+    select CEVT_R4K
>> >+    select CPU_HAS_WB
>> >+    select HW_HAS_PCI
>> >+    select ISA
>> >+    select I8259
>> >+    select IRQ_CPU
>> >+    select SYS_HAS_CPU_LOONGSON3
>> >+    select SYS_HAS_EARLY_PRINTK
>> >+    select SYS_SUPPORTS_SMP
>> >+    select SYS_SUPPORTS_64BIT_KERNEL
>> >+    select SYS_SUPPORTS_HIGHMEM
>> >+    select SYS_SUPPORTS_LITTLE_ENDIAN
>> >+    select LOONGSON_MC146818
>> >+    select ZONE_DMA32 if 64BIT
>> >+    select LEFI_FIRMWARE_INTERFACE
>> >+    help
>> >+            Lemote Loongson 3A family machines utilize the 3A revision of
>> >+            Loongson processor and RS780/SBX00 chipset.
>> >  endchoice
>>
>> Add "select NR_CPUS_DEFAULT_4" on here? Currently creating a
>> configuration without using the loongson3_defconfig will default to
>> 2, but unless I'm mistaken, all 3A machines are quad core?
>>
>> >
>> >  config CS5536
>> >@@ -86,8 +114,24 @@ config LOONGSON_UART_BASE
>> >     default y
>> >     depends on EARLY_PRINTK || SERIAL_8250
>> >
>> >+config IOMMU_HELPER
>> >+    bool
>> >+
>> >+config NEED_SG_DMA_LENGTH
>> >+    bool
>> >+
>> >+config SWIOTLB
>> >+    bool "Soft IOMMU Support for Big Memory (>4GB)"
>> >+    depends on CPU_LOONGSON3
>> >+    select IOMMU_HELPER
>> >+    select NEED_SG_DMA_LENGTH
>> >+    select NEED_DMA_MAP_STATE
>> >+
>>
>> Again, default to y?
>>
>> Thanks,
>> Alex
>>
>> >  config LOONGSON_MC146818
>> >     bool
>> >     default n
>> >
>> >+config LEFI_FIRMWARE_INTERFACE
>> >+    bool
>> >+
>> >  endif # MACH_LOONGSON
>> >diff --git a/arch/mips/loongson/Platform b/arch/mips/loongson/Platform
>> >index 29692e5..6205372 100644
>> >--- a/arch/mips/loongson/Platform
>> >+++ b/arch/mips/loongson/Platform
>> >@@ -30,3 +30,4 @@ platform-$(CONFIG_MACH_LOONGSON) += loongson/
>> >  cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely
>> >  load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000
>> >  load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000
>> >+load-$(CONFIG_CPU_LOONGSON3) += 0xffffffff80200000
>> >
>>
>>
>
> --
> Aurelien Jarno                          GPG: 1024D/F1BCDB73
> aurelien@aurel32.net                 http://www.aurel32.net
>

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

* Re: [PATCH V16 09/12] MIPS: Loongson: Add Loongson-3 Kconfig options
  2014-01-13  3:02       ` Huacai Chen
@ 2014-01-13  4:30         ` Aurelien Jarno
  2014-01-13 10:15           ` Huacai Chen
  0 siblings, 1 reply; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-13  4:30 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Alex Smith, Ralf Baechle, John Crispin, Steven J. Hill,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Mon, Jan 13, 2014 at 11:02:19AM +0800, Huacai Chen wrote:
> On Sat, Jan 11, 2014 at 11:24 PM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> > On Thu, Jan 09, 2014 at 01:07:30PM +0000, Alex Smith wrote:
> >> On 08/01/14 02:44, Huacai Chen wrote:
> >> >Added Kconfig options include: Loongson-3 CPU and machine definition,
> >> >CPU cache features, UEFI-like firmware interface (LEFI), HT-linked PCI,
> >> >and big memory support.
> >> >
> >> >Signed-off-by: Huacai Chen <chenhc@lemote.com>
> >> >Signed-off-by: Hongliang Tao <taohl@lemote.com>
> >> >Signed-off-by: Hua Yan <yanh@lemote.com>
> >> >---
> >> >  arch/mips/Kconfig           |   29 +++++++++++++++++++++++++++-
> >> >  arch/mips/loongson/Kconfig  |   44 +++++++++++++++++++++++++++++++++++++++++++
> >> >  arch/mips/loongson/Platform |    1 +
> >> >  3 files changed, 73 insertions(+), 1 deletions(-)
> >> >
> >> >diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> >> >index 17cc7ff..513e941 100644
> >> >--- a/arch/mips/Kconfig
> >> >+++ b/arch/mips/Kconfig
> >> >@@ -1487,6 +1487,18 @@ config CPU_LOONGSON2
> >> >     select CPU_SUPPORTS_HIGHMEM
> >> >     select CPU_SUPPORTS_HUGEPAGES
> >> >
> >> >+config CPU_LOONGSON3
> >> >+    bool "Loongson 3 CPU"
> >> >+    depends on SYS_HAS_CPU_LOONGSON3
> >> >+    select CPU_SUPPORTS_64BIT_KERNEL
> >> >+    select CPU_SUPPORTS_HIGHMEM
> >> >+    select CPU_SUPPORTS_HUGEPAGES
> >> >+    select WEAK_ORDERING
> >> >+    select WEAK_REORDERING_BEYOND_LLSC
> >> >+    help
> >> >+            The Loongson 3 processor implements the MIPS III instruction set
> >> >+            with many extensions.
> >> >+
> >>
> >> This should be moved into the "CPU type" choice block. Currently
> >> this appears as an option outside of that choice, and so it is
> >> possible to build a kernel without any CPU type selected.
> >>
> >> Also, as Aurelien said on the previous version, shouldn't the
> >> comment be changed to MIPS64R2 rather than MIPS III even if you
> >> aren't selecting the MIPS64 CPU types for the time being? Note, if
> >> you replied to that comment I may not have seen it - I think the
> >> list is filtering your replies because they're HTML emails.
> >>
> >> >  config CPU_LOONGSON1
> >> >     bool
> >> >     select CPU_MIPS32
> >> >@@ -1513,6 +1526,10 @@ config SYS_HAS_CPU_LOONGSON2F
> >> >     select CPU_SUPPORTS_ADDRWINCFG if 64BIT
> >> >     select CPU_SUPPORTS_UNCACHED_ACCELERATED
> >> >
> >> >+config SYS_HAS_CPU_LOONGSON3
> >> >+    bool
> >> >+    select CPU_SUPPORTS_CPUFREQ
> >> >+
> >> >  config SYS_HAS_CPU_LOONGSON1B
> >> >     bool
> >> >
> >> >@@ -1703,7 +1720,7 @@ choice
> >> >
> >> >  config PAGE_SIZE_4KB
> >> >     bool "4kB"
> >> >-    depends on !CPU_LOONGSON2
> >> >+    depends on !CPU_LOONGSON2 && !CPU_LOONGSON3
> >> >     help
> >> >      This option select the standard 4kB Linux page size.  On some
> >> >      R3000-family processors this is the only available page size.  Using
> >> >@@ -2373,6 +2390,16 @@ config PCI
> >> >       your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
> >> >       say Y, otherwise N.
> >> >
> >> >+config HT_PCI
> >> >+    bool "Support for HT-linked PCI"
> >> >+    depends on CPU_LOONGSON3
> >> >+    select PCI_DOMAINS
> >> >+    help
> >> >+      Loongson family machines use Hyper-Transport bus for inter-core
> >> >+      connection and device connection. The PCI bus is a subordinate
> >> >+      linked at HT. Choose Y unless you are using Loongson 2E/2F based
> >> >+      machines.
> >> >+
> >>
> >> Should this default to y, given that it is selected in the
> >> defconfig? Also, the comment referring to 2E/2F is redundant given
> >> that it depends on CPU_LOONGSON3 and cannot be selected on those
> >> machines.
> >
> > I am still not sure we need such an option. This option only changes an
> > address in arch/mips/include/asm/mach-loongson/loongson.h:
> >
> > | #if defined(CONFIG_HT_PCI)
> > | #define LOONGSON_PCIIO_BASE     loongson_sysconf.pci_io_base
> > | #else
> > | #define LOONGSON_PCIIO_BASE     0x1fd00000
> > | #endif
> >
> > If both options are working on a Loongson 3 machine, it's definitely a
> > good idea to leave the choice to the user. That said if only the address
> > from loongson_sysconf.pci_io_base works on a Loongson 3 machine, this
> > option must always be selected and is therefore useless.
> HT_PCI is needed, because Loongson-3 device structure looks like this:
> Loongson3-Core -----       ---- MEM
>          |--- Cache ---|
> HT1-controller  -------       ---- PCI-Controller --- PCI-Devices (PATH-B)
>     |
>     |
>  PCI-Controller
>     |
>     |
>  PCI-Devices (PATH-A)
> 
> If PCI devices are linked via PATH-A, we should select HT_PCI;
> otherwise we should unselected HT_PCI.

Thanks for the explanation, it looks now more clear why we need this
option. Both cases are valid, it just depends on where the PCI
controller is connected.

That said it means that we won't be able to use the same kernel on
machines using the PATH-A and on machines using the PATH-B. Is there
a way to determine this at runtime through LEFI?

Aurelien

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 09/12] MIPS: Loongson: Add Loongson-3 Kconfig options
  2014-01-13  4:30         ` Aurelien Jarno
@ 2014-01-13 10:15           ` Huacai Chen
  2014-01-13 10:38             ` Aurelien Jarno
  0 siblings, 1 reply; 55+ messages in thread
From: Huacai Chen @ 2014-01-13 10:15 UTC (permalink / raw)
  To: Aurelien Jarno
  Cc: Alex Smith, Ralf Baechle, John Crispin, Steven J. Hill,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Mon, Jan 13, 2014 at 12:30 PM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> On Mon, Jan 13, 2014 at 11:02:19AM +0800, Huacai Chen wrote:
>> On Sat, Jan 11, 2014 at 11:24 PM, Aurelien Jarno <aurelien@aurel32.net> wrote:
>> > On Thu, Jan 09, 2014 at 01:07:30PM +0000, Alex Smith wrote:
>> >> On 08/01/14 02:44, Huacai Chen wrote:
>> >> >Added Kconfig options include: Loongson-3 CPU and machine definition,
>> >> >CPU cache features, UEFI-like firmware interface (LEFI), HT-linked PCI,
>> >> >and big memory support.
>> >> >
>> >> >Signed-off-by: Huacai Chen <chenhc@lemote.com>
>> >> >Signed-off-by: Hongliang Tao <taohl@lemote.com>
>> >> >Signed-off-by: Hua Yan <yanh@lemote.com>
>> >> >---
>> >> >  arch/mips/Kconfig           |   29 +++++++++++++++++++++++++++-
>> >> >  arch/mips/loongson/Kconfig  |   44 +++++++++++++++++++++++++++++++++++++++++++
>> >> >  arch/mips/loongson/Platform |    1 +
>> >> >  3 files changed, 73 insertions(+), 1 deletions(-)
>> >> >
>> >> >diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
>> >> >index 17cc7ff..513e941 100644
>> >> >--- a/arch/mips/Kconfig
>> >> >+++ b/arch/mips/Kconfig
>> >> >@@ -1487,6 +1487,18 @@ config CPU_LOONGSON2
>> >> >     select CPU_SUPPORTS_HIGHMEM
>> >> >     select CPU_SUPPORTS_HUGEPAGES
>> >> >
>> >> >+config CPU_LOONGSON3
>> >> >+    bool "Loongson 3 CPU"
>> >> >+    depends on SYS_HAS_CPU_LOONGSON3
>> >> >+    select CPU_SUPPORTS_64BIT_KERNEL
>> >> >+    select CPU_SUPPORTS_HIGHMEM
>> >> >+    select CPU_SUPPORTS_HUGEPAGES
>> >> >+    select WEAK_ORDERING
>> >> >+    select WEAK_REORDERING_BEYOND_LLSC
>> >> >+    help
>> >> >+            The Loongson 3 processor implements the MIPS III instruction set
>> >> >+            with many extensions.
>> >> >+
>> >>
>> >> This should be moved into the "CPU type" choice block. Currently
>> >> this appears as an option outside of that choice, and so it is
>> >> possible to build a kernel without any CPU type selected.
>> >>
>> >> Also, as Aurelien said on the previous version, shouldn't the
>> >> comment be changed to MIPS64R2 rather than MIPS III even if you
>> >> aren't selecting the MIPS64 CPU types for the time being? Note, if
>> >> you replied to that comment I may not have seen it - I think the
>> >> list is filtering your replies because they're HTML emails.
>> >>
>> >> >  config CPU_LOONGSON1
>> >> >     bool
>> >> >     select CPU_MIPS32
>> >> >@@ -1513,6 +1526,10 @@ config SYS_HAS_CPU_LOONGSON2F
>> >> >     select CPU_SUPPORTS_ADDRWINCFG if 64BIT
>> >> >     select CPU_SUPPORTS_UNCACHED_ACCELERATED
>> >> >
>> >> >+config SYS_HAS_CPU_LOONGSON3
>> >> >+    bool
>> >> >+    select CPU_SUPPORTS_CPUFREQ
>> >> >+
>> >> >  config SYS_HAS_CPU_LOONGSON1B
>> >> >     bool
>> >> >
>> >> >@@ -1703,7 +1720,7 @@ choice
>> >> >
>> >> >  config PAGE_SIZE_4KB
>> >> >     bool "4kB"
>> >> >-    depends on !CPU_LOONGSON2
>> >> >+    depends on !CPU_LOONGSON2 && !CPU_LOONGSON3
>> >> >     help
>> >> >      This option select the standard 4kB Linux page size.  On some
>> >> >      R3000-family processors this is the only available page size.  Using
>> >> >@@ -2373,6 +2390,16 @@ config PCI
>> >> >       your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
>> >> >       say Y, otherwise N.
>> >> >
>> >> >+config HT_PCI
>> >> >+    bool "Support for HT-linked PCI"
>> >> >+    depends on CPU_LOONGSON3
>> >> >+    select PCI_DOMAINS
>> >> >+    help
>> >> >+      Loongson family machines use Hyper-Transport bus for inter-core
>> >> >+      connection and device connection. The PCI bus is a subordinate
>> >> >+      linked at HT. Choose Y unless you are using Loongson 2E/2F based
>> >> >+      machines.
>> >> >+
>> >>
>> >> Should this default to y, given that it is selected in the
>> >> defconfig? Also, the comment referring to 2E/2F is redundant given
>> >> that it depends on CPU_LOONGSON3 and cannot be selected on those
>> >> machines.
>> >
>> > I am still not sure we need such an option. This option only changes an
>> > address in arch/mips/include/asm/mach-loongson/loongson.h:
>> >
>> > | #if defined(CONFIG_HT_PCI)
>> > | #define LOONGSON_PCIIO_BASE     loongson_sysconf.pci_io_base
>> > | #else
>> > | #define LOONGSON_PCIIO_BASE     0x1fd00000
>> > | #endif
>> >
>> > If both options are working on a Loongson 3 machine, it's definitely a
>> > good idea to leave the choice to the user. That said if only the address
>> > from loongson_sysconf.pci_io_base works on a Loongson 3 machine, this
>> > option must always be selected and is therefore useless.
>> HT_PCI is needed, because Loongson-3 device structure looks like this:
>> Loongson3-Core -----       ---- MEM
>>          |--- Cache ---|
>> HT1-controller  -------       ---- PCI-Controller --- PCI-Devices (PATH-B)
>>     |
>>     |
>>  PCI-Controller
>>     |
>>     |
>>  PCI-Devices (PATH-A)
>>
>> If PCI devices are linked via PATH-A, we should select HT_PCI;
>> otherwise we should unselected HT_PCI.
>
> Thanks for the explanation, it looks now more clear why we need this
> option. Both cases are valid, it just depends on where the PCI
> controller is connected.
>
> That said it means that we won't be able to use the same kernel on
> machines using the PATH-A and on machines using the PATH-B. Is there
> a way to determine this at runtime through LEFI?
At present we can't determine PATH-A/B through LEFI, and LEFI is
surely need to extend at some time. Most of machines use PATH-A, since
in this way DMA coherency is maintained by hardware. If use PATH-B,
both HT_PCI and LEFI should be disabled.

>
> Aurelien
>
> --
> Aurelien Jarno                          GPG: 1024D/F1BCDB73
> aurelien@aurel32.net                 http://www.aurel32.net
>

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

* Re: [PATCH V16 09/12] MIPS: Loongson: Add Loongson-3 Kconfig options
  2014-01-13 10:15           ` Huacai Chen
@ 2014-01-13 10:38             ` Aurelien Jarno
  2014-01-13 12:15               ` Huacai Chen
  0 siblings, 1 reply; 55+ messages in thread
From: Aurelien Jarno @ 2014-01-13 10:38 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Alex Smith, Ralf Baechle, John Crispin, Steven J. Hill,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Mon, Jan 13, 2014 at 06:15:26PM +0800, Huacai Chen wrote:
> On Mon, Jan 13, 2014 at 12:30 PM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> > On Mon, Jan 13, 2014 at 11:02:19AM +0800, Huacai Chen wrote:
> >> On Sat, Jan 11, 2014 at 11:24 PM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> >> > On Thu, Jan 09, 2014 at 01:07:30PM +0000, Alex Smith wrote:
> >> >> On 08/01/14 02:44, Huacai Chen wrote:
> >> >> >Added Kconfig options include: Loongson-3 CPU and machine definition,
> >> >> >CPU cache features, UEFI-like firmware interface (LEFI), HT-linked PCI,
> >> >> >and big memory support.
> >> >> >
> >> >> >Signed-off-by: Huacai Chen <chenhc@lemote.com>
> >> >> >Signed-off-by: Hongliang Tao <taohl@lemote.com>
> >> >> >Signed-off-by: Hua Yan <yanh@lemote.com>
> >> >> >---
> >> >> >  arch/mips/Kconfig           |   29 +++++++++++++++++++++++++++-
> >> >> >  arch/mips/loongson/Kconfig  |   44 +++++++++++++++++++++++++++++++++++++++++++
> >> >> >  arch/mips/loongson/Platform |    1 +
> >> >> >  3 files changed, 73 insertions(+), 1 deletions(-)
> >> >> >
> >> >> >diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> >> >> >index 17cc7ff..513e941 100644
> >> >> >--- a/arch/mips/Kconfig
> >> >> >+++ b/arch/mips/Kconfig
> >> >> >@@ -1487,6 +1487,18 @@ config CPU_LOONGSON2
> >> >> >     select CPU_SUPPORTS_HIGHMEM
> >> >> >     select CPU_SUPPORTS_HUGEPAGES
> >> >> >
> >> >> >+config CPU_LOONGSON3
> >> >> >+    bool "Loongson 3 CPU"
> >> >> >+    depends on SYS_HAS_CPU_LOONGSON3
> >> >> >+    select CPU_SUPPORTS_64BIT_KERNEL
> >> >> >+    select CPU_SUPPORTS_HIGHMEM
> >> >> >+    select CPU_SUPPORTS_HUGEPAGES
> >> >> >+    select WEAK_ORDERING
> >> >> >+    select WEAK_REORDERING_BEYOND_LLSC
> >> >> >+    help
> >> >> >+            The Loongson 3 processor implements the MIPS III instruction set
> >> >> >+            with many extensions.
> >> >> >+
> >> >>
> >> >> This should be moved into the "CPU type" choice block. Currently
> >> >> this appears as an option outside of that choice, and so it is
> >> >> possible to build a kernel without any CPU type selected.
> >> >>
> >> >> Also, as Aurelien said on the previous version, shouldn't the
> >> >> comment be changed to MIPS64R2 rather than MIPS III even if you
> >> >> aren't selecting the MIPS64 CPU types for the time being? Note, if
> >> >> you replied to that comment I may not have seen it - I think the
> >> >> list is filtering your replies because they're HTML emails.
> >> >>
> >> >> >  config CPU_LOONGSON1
> >> >> >     bool
> >> >> >     select CPU_MIPS32
> >> >> >@@ -1513,6 +1526,10 @@ config SYS_HAS_CPU_LOONGSON2F
> >> >> >     select CPU_SUPPORTS_ADDRWINCFG if 64BIT
> >> >> >     select CPU_SUPPORTS_UNCACHED_ACCELERATED
> >> >> >
> >> >> >+config SYS_HAS_CPU_LOONGSON3
> >> >> >+    bool
> >> >> >+    select CPU_SUPPORTS_CPUFREQ
> >> >> >+
> >> >> >  config SYS_HAS_CPU_LOONGSON1B
> >> >> >     bool
> >> >> >
> >> >> >@@ -1703,7 +1720,7 @@ choice
> >> >> >
> >> >> >  config PAGE_SIZE_4KB
> >> >> >     bool "4kB"
> >> >> >-    depends on !CPU_LOONGSON2
> >> >> >+    depends on !CPU_LOONGSON2 && !CPU_LOONGSON3
> >> >> >     help
> >> >> >      This option select the standard 4kB Linux page size.  On some
> >> >> >      R3000-family processors this is the only available page size.  Using
> >> >> >@@ -2373,6 +2390,16 @@ config PCI
> >> >> >       your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
> >> >> >       say Y, otherwise N.
> >> >> >
> >> >> >+config HT_PCI
> >> >> >+    bool "Support for HT-linked PCI"
> >> >> >+    depends on CPU_LOONGSON3
> >> >> >+    select PCI_DOMAINS
> >> >> >+    help
> >> >> >+      Loongson family machines use Hyper-Transport bus for inter-core
> >> >> >+      connection and device connection. The PCI bus is a subordinate
> >> >> >+      linked at HT. Choose Y unless you are using Loongson 2E/2F based
> >> >> >+      machines.
> >> >> >+
> >> >>
> >> >> Should this default to y, given that it is selected in the
> >> >> defconfig? Also, the comment referring to 2E/2F is redundant given
> >> >> that it depends on CPU_LOONGSON3 and cannot be selected on those
> >> >> machines.
> >> >
> >> > I am still not sure we need such an option. This option only changes an
> >> > address in arch/mips/include/asm/mach-loongson/loongson.h:
> >> >
> >> > | #if defined(CONFIG_HT_PCI)
> >> > | #define LOONGSON_PCIIO_BASE     loongson_sysconf.pci_io_base
> >> > | #else
> >> > | #define LOONGSON_PCIIO_BASE     0x1fd00000
> >> > | #endif
> >> >
> >> > If both options are working on a Loongson 3 machine, it's definitely a
> >> > good idea to leave the choice to the user. That said if only the address
> >> > from loongson_sysconf.pci_io_base works on a Loongson 3 machine, this
> >> > option must always be selected and is therefore useless.
> >> HT_PCI is needed, because Loongson-3 device structure looks like this:
> >> Loongson3-Core -----       ---- MEM
> >>          |--- Cache ---|
> >> HT1-controller  -------       ---- PCI-Controller --- PCI-Devices (PATH-B)
> >>     |
> >>     |
> >>  PCI-Controller
> >>     |
> >>     |
> >>  PCI-Devices (PATH-A)
> >>
> >> If PCI devices are linked via PATH-A, we should select HT_PCI;
> >> otherwise we should unselected HT_PCI.
> >
> > Thanks for the explanation, it looks now more clear why we need this
> > option. Both cases are valid, it just depends on where the PCI
> > controller is connected.
> >
> > That said it means that we won't be able to use the same kernel on
> > machines using the PATH-A and on machines using the PATH-B. Is there
> > a way to determine this at runtime through LEFI?
> At present we can't determine PATH-A/B through LEFI, and LEFI is
> surely need to extend at some time. Most of machines use PATH-A, since
> in this way DMA coherency is maintained by hardware. If use PATH-B,
> both HT_PCI and LEFI should be disabled.

As far as I understand, the current patchset assumes DMA coherency in
all the patches. It means that even if this option is disabled to use
the PATH-B instead, it won't work correctly.

Therefore I think that this option should not be given to the user,
either LEMOTE_MACH3A should automatically select it, or it should simply
be removed. Of course it could be reintroduced in a later patchset
adding full support for machines having their PCI connected through
PATH-B.

Aurelien

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH V16 09/12] MIPS: Loongson: Add Loongson-3 Kconfig options
  2014-01-13 10:38             ` Aurelien Jarno
@ 2014-01-13 12:15               ` Huacai Chen
  0 siblings, 0 replies; 55+ messages in thread
From: Huacai Chen @ 2014-01-13 12:15 UTC (permalink / raw)
  To: Aurelien Jarno
  Cc: Alex Smith, Ralf Baechle, John Crispin, Steven J. Hill,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

On Mon, Jan 13, 2014 at 6:38 PM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> On Mon, Jan 13, 2014 at 06:15:26PM +0800, Huacai Chen wrote:
>> On Mon, Jan 13, 2014 at 12:30 PM, Aurelien Jarno <aurelien@aurel32.net> wrote:
>> > On Mon, Jan 13, 2014 at 11:02:19AM +0800, Huacai Chen wrote:
>> >> On Sat, Jan 11, 2014 at 11:24 PM, Aurelien Jarno <aurelien@aurel32.net> wrote:
>> >> > On Thu, Jan 09, 2014 at 01:07:30PM +0000, Alex Smith wrote:
>> >> >> On 08/01/14 02:44, Huacai Chen wrote:
>> >> >> >Added Kconfig options include: Loongson-3 CPU and machine definition,
>> >> >> >CPU cache features, UEFI-like firmware interface (LEFI), HT-linked PCI,
>> >> >> >and big memory support.
>> >> >> >
>> >> >> >Signed-off-by: Huacai Chen <chenhc@lemote.com>
>> >> >> >Signed-off-by: Hongliang Tao <taohl@lemote.com>
>> >> >> >Signed-off-by: Hua Yan <yanh@lemote.com>
>> >> >> >---
>> >> >> >  arch/mips/Kconfig           |   29 +++++++++++++++++++++++++++-
>> >> >> >  arch/mips/loongson/Kconfig  |   44 +++++++++++++++++++++++++++++++++++++++++++
>> >> >> >  arch/mips/loongson/Platform |    1 +
>> >> >> >  3 files changed, 73 insertions(+), 1 deletions(-)
>> >> >> >
>> >> >> >diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
>> >> >> >index 17cc7ff..513e941 100644
>> >> >> >--- a/arch/mips/Kconfig
>> >> >> >+++ b/arch/mips/Kconfig
>> >> >> >@@ -1487,6 +1487,18 @@ config CPU_LOONGSON2
>> >> >> >     select CPU_SUPPORTS_HIGHMEM
>> >> >> >     select CPU_SUPPORTS_HUGEPAGES
>> >> >> >
>> >> >> >+config CPU_LOONGSON3
>> >> >> >+    bool "Loongson 3 CPU"
>> >> >> >+    depends on SYS_HAS_CPU_LOONGSON3
>> >> >> >+    select CPU_SUPPORTS_64BIT_KERNEL
>> >> >> >+    select CPU_SUPPORTS_HIGHMEM
>> >> >> >+    select CPU_SUPPORTS_HUGEPAGES
>> >> >> >+    select WEAK_ORDERING
>> >> >> >+    select WEAK_REORDERING_BEYOND_LLSC
>> >> >> >+    help
>> >> >> >+            The Loongson 3 processor implements the MIPS III instruction set
>> >> >> >+            with many extensions.
>> >> >> >+
>> >> >>
>> >> >> This should be moved into the "CPU type" choice block. Currently
>> >> >> this appears as an option outside of that choice, and so it is
>> >> >> possible to build a kernel without any CPU type selected.
>> >> >>
>> >> >> Also, as Aurelien said on the previous version, shouldn't the
>> >> >> comment be changed to MIPS64R2 rather than MIPS III even if you
>> >> >> aren't selecting the MIPS64 CPU types for the time being? Note, if
>> >> >> you replied to that comment I may not have seen it - I think the
>> >> >> list is filtering your replies because they're HTML emails.
>> >> >>
>> >> >> >  config CPU_LOONGSON1
>> >> >> >     bool
>> >> >> >     select CPU_MIPS32
>> >> >> >@@ -1513,6 +1526,10 @@ config SYS_HAS_CPU_LOONGSON2F
>> >> >> >     select CPU_SUPPORTS_ADDRWINCFG if 64BIT
>> >> >> >     select CPU_SUPPORTS_UNCACHED_ACCELERATED
>> >> >> >
>> >> >> >+config SYS_HAS_CPU_LOONGSON3
>> >> >> >+    bool
>> >> >> >+    select CPU_SUPPORTS_CPUFREQ
>> >> >> >+
>> >> >> >  config SYS_HAS_CPU_LOONGSON1B
>> >> >> >     bool
>> >> >> >
>> >> >> >@@ -1703,7 +1720,7 @@ choice
>> >> >> >
>> >> >> >  config PAGE_SIZE_4KB
>> >> >> >     bool "4kB"
>> >> >> >-    depends on !CPU_LOONGSON2
>> >> >> >+    depends on !CPU_LOONGSON2 && !CPU_LOONGSON3
>> >> >> >     help
>> >> >> >      This option select the standard 4kB Linux page size.  On some
>> >> >> >      R3000-family processors this is the only available page size.  Using
>> >> >> >@@ -2373,6 +2390,16 @@ config PCI
>> >> >> >       your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
>> >> >> >       say Y, otherwise N.
>> >> >> >
>> >> >> >+config HT_PCI
>> >> >> >+    bool "Support for HT-linked PCI"
>> >> >> >+    depends on CPU_LOONGSON3
>> >> >> >+    select PCI_DOMAINS
>> >> >> >+    help
>> >> >> >+      Loongson family machines use Hyper-Transport bus for inter-core
>> >> >> >+      connection and device connection. The PCI bus is a subordinate
>> >> >> >+      linked at HT. Choose Y unless you are using Loongson 2E/2F based
>> >> >> >+      machines.
>> >> >> >+
>> >> >>
>> >> >> Should this default to y, given that it is selected in the
>> >> >> defconfig? Also, the comment referring to 2E/2F is redundant given
>> >> >> that it depends on CPU_LOONGSON3 and cannot be selected on those
>> >> >> machines.
>> >> >
>> >> > I am still not sure we need such an option. This option only changes an
>> >> > address in arch/mips/include/asm/mach-loongson/loongson.h:
>> >> >
>> >> > | #if defined(CONFIG_HT_PCI)
>> >> > | #define LOONGSON_PCIIO_BASE     loongson_sysconf.pci_io_base
>> >> > | #else
>> >> > | #define LOONGSON_PCIIO_BASE     0x1fd00000
>> >> > | #endif
>> >> >
>> >> > If both options are working on a Loongson 3 machine, it's definitely a
>> >> > good idea to leave the choice to the user. That said if only the address
>> >> > from loongson_sysconf.pci_io_base works on a Loongson 3 machine, this
>> >> > option must always be selected and is therefore useless.
>> >> HT_PCI is needed, because Loongson-3 device structure looks like this:
>> >> Loongson3-Core -----       ---- MEM
>> >>          |--- Cache ---|
>> >> HT1-controller  -------       ---- PCI-Controller --- PCI-Devices (PATH-B)
>> >>     |
>> >>     |
>> >>  PCI-Controller
>> >>     |
>> >>     |
>> >>  PCI-Devices (PATH-A)
>> >>
>> >> If PCI devices are linked via PATH-A, we should select HT_PCI;
>> >> otherwise we should unselected HT_PCI.
>> >
>> > Thanks for the explanation, it looks now more clear why we need this
>> > option. Both cases are valid, it just depends on where the PCI
>> > controller is connected.
>> >
>> > That said it means that we won't be able to use the same kernel on
>> > machines using the PATH-A and on machines using the PATH-B. Is there
>> > a way to determine this at runtime through LEFI?
>> At present we can't determine PATH-A/B through LEFI, and LEFI is
>> surely need to extend at some time. Most of machines use PATH-A, since
>> in this way DMA coherency is maintained by hardware. If use PATH-B,
>> both HT_PCI and LEFI should be disabled.
>
> As far as I understand, the current patchset assumes DMA coherency in
> all the patches. It means that even if this option is disabled to use
> the PATH-B instead, it won't work correctly.
>
> Therefore I think that this option should not be given to the user,
> either LEMOTE_MACH3A should automatically select it, or it should simply
> be removed. Of course it could be reintroduced in a later patchset
> adding full support for machines having their PCI connected through
> PATH-B.
OK, I'll make LEMOTE_MACH3A select HT_PCI automatically.

>
> Aurelien
>
> --
> Aurelien Jarno                          GPG: 1024D/F1BCDB73
> aurelien@aurel32.net                 http://www.aurel32.net
>

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

* Re: [PATCH V16 02/12] MIPS: Loongson: Add basic Loongson-3 CPU support
  2014-01-12 12:10             ` Aaro Koskinen
@ 2014-01-18  1:54               ` John Crispin
  0 siblings, 0 replies; 55+ messages in thread
From: John Crispin @ 2014-01-18  1:54 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Aaro Koskinen, Aurelien Jarno, linux-mips, Fuxin Zhang,
	Hongliang Tao, Hua Yan

Hi,

On 12/01/2014 13:10, Aaro Koskinen wrote:
>>>>>> As remarked by Aaro Koskinen, changing the names of the Loongson 2 CPUs
>>>>>> > > >> > (which is displayedd in /proc/cpuinfo) will break at least
>>>>>> > > >> > GCC -march=native option. The name should be left unchanged.
>>>>>> > > >> >
>>>>> > > >> Can I keep it as is and then submit a patch to GCC? I think it is important
>>>>> > > >> to distinguish 2E/2F/3A in cpuinfo.
>>>> > > >
>>>> > > > I think first the patch has to be integrated to GCC, and then you have
>>>> > > > to wait at least a few months so that people start using the new
>>>> > > > version. Then it should be possible to modify this.
>>>> > > >
>>>> > > > That said, other programs than GCC might use this information from
>>>> > > > /proc/cpuinfo and might also break with this change.
>>> > > The GCC patch has been accepted yesterday, and the coming V17 patchset
>>> > > won't be accept at least in kernel-3.14,
>>> > > So, I'll keep the name in V17.
>> > 
>> > Kernel 3.15 is expected in roughly 6 months, it might still be a bit
>> > tight for the change to propagate, even if I have seen it has been added
>> > to the 4.8 branch. What the others things? Aaro?
> It doesn't really matter if some future version of GCC supports the
> new name. Most people will continue to use older toolchains for years,
> and we shouldn't change the behaviour of those.
>
> A.
>

NAK

Breaking the ABI is a really bad idea. I cannot think of any valid
reason that would allow me to merge this change.

    John

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

* Re: [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support
  2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
                   ` (12 preceding siblings ...)
  2014-01-08  7:26 ` [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support John Crispin
@ 2014-01-18  9:38 ` Andreas Barth
       [not found]   ` <0466fa9d60b91233d2157d5ce0b51333.squirrel@mail.lemote.com>
  13 siblings, 1 reply; 55+ messages in thread
From: Andreas Barth @ 2014-01-18  9:38 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, Aurelien Jarno,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

Hi,


* Huacai Chen (chenhc@lemote.com) [140108 03:45]:
> This patchset is prepared for the next 3.14 release for Linux/MIPS.
> Loongson-3 is a multi-core MIPS family CPU, it is MIPS64R2 compatible
> and has the same IMP field (0x6300) as Loongson-2. These patches make
> Linux kernel support Loongson-3 CPU and Loongson-3 based computers
> (including Laptop, Mini-ITX, All-In-One PC, etc.)

Your patch series already made some good progress, and so I hope that
we manage to get this patch merged during the next cycle (i.e. during
3.15).

To achive this it would be good if you could incorporate the remaining
review comments into a new version and send it out soon. (We should
try to get it ready as soon as possible even if it won't be in 3.14,
so that we are sure to really reach 3.15 and not be delayed again.)


Thanks,
Andi

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

* Re: [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support
       [not found]   ` <0466fa9d60b91233d2157d5ce0b51333.squirrel@mail.lemote.com>
@ 2014-02-06 23:27     ` Andreas Barth
  0 siblings, 0 replies; 55+ messages in thread
From: Andreas Barth @ 2014-02-06 23:27 UTC (permalink / raw)
  To: 陈华才
  Cc: Ralf Baechle, John Crispin, Steven J. Hill, Aurelien Jarno,
	linux-mips, Fuxin Zhang, Zhangjin Wu, Hongliang Tao, Hua Yan

Hi,

* "陈华才" (chenhc@lemote.com) [140118 13:14]:
> > * Huacai Chen (chenhc@lemote.com) [140108 03:45]:
> >> This patchset is prepared for the next 3.14 release for Linux/MIPS.
> >> Loongson-3 is a multi-core MIPS family CPU, it is MIPS64R2 compatible
> >> and has the same IMP field (0x6300) as Loongson-2. These patches make
> >> Linux kernel support Loongson-3 CPU and Loongson-3 based computers
> >> (including Laptop, Mini-ITX, All-In-One PC, etc.)
> >
> > Your patch series already made some good progress, and so I hope that
> > we manage to get this patch merged during the next cycle (i.e. during
> > 3.15).
> >
> > To achive this it would be good if you could incorporate the remaining
> > review comments into a new version and send it out soon. (We should
> > try to get it ready as soon as possible even if it won't be in 3.14,
> > so that we are sure to really reach 3.15 and not be delayed again.)

> Thank you very much, I will make the V17 patchset ready for 3.15 after
> China's New Year's Day.

I hope you had a happy new year.


Do you have any updates when we can expect the new patch sets? If we
want/need another round of reviews, we need to have the patch soon, so
that it could be pushed to -next in time for the next merge cycle.


Thanks,
Andi

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

end of thread, other threads:[~2014-02-06 23:28 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-01-08  2:44 [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support Huacai Chen
2014-01-08  2:44 ` [PATCH V16 01/12] MIPS: Loongson: Add basic Loongson-3 definition Huacai Chen
2014-01-08 19:58   ` Aurelien Jarno
2014-01-08  2:44 ` [PATCH V16 02/12] MIPS: Loongson: Add basic Loongson-3 CPU support Huacai Chen
2014-01-08 19:58   ` Aurelien Jarno
     [not found]     ` <CAAhV-H4tx=sCk=iUwuCfnCS+rbmtu5Y_UcpAn6JXDoobA+OGrQ@mail.gmail.com>
2014-01-09 21:36       ` Aurelien Jarno
2014-01-12  9:03         ` Huacai Chen
2014-01-12  9:57           ` Aurelien Jarno
2014-01-12 12:10             ` Aaro Koskinen
2014-01-18  1:54               ` John Crispin
2014-01-08  2:44 ` [PATCH V16 03/12] MIPS: Loongson 3: Add Lemote-3A machtypes definition Huacai Chen
2014-01-08 19:58   ` Aurelien Jarno
2014-01-08  2:44 ` [PATCH V16 04/12] MIPS: Loongson: Add UEFI-like firmware interface (LEFI) support Huacai Chen
2014-01-08 22:58   ` Aurelien Jarno
2014-01-09 12:43     ` Alex Smith
2014-01-09 12:43       ` Alex Smith
     [not found]     ` <CAAhV-H64BXsw5CBL-KW1eqXkYcadhHF2NeBH9YmWQz046Lpzzw@mail.gmail.com>
2014-01-09 21:37       ` Aurelien Jarno
2014-01-09 12:37   ` Alex Smith
2014-01-09 12:37     ` Alex Smith
2014-01-08  2:44 ` [PATCH V16 05/12] MIPS: Loongson 3: Add HT-linked PCI support Huacai Chen
2014-01-08 22:58   ` Aurelien Jarno
     [not found]     ` <CAAhV-H57tDmYByjVwhf3teFZkGowR4E9+OO1vO0kP3iAKTNJVw@mail.gmail.com>
2014-01-09 21:38       ` Aurelien Jarno
2014-01-08  2:44 ` [PATCH V16 06/12] MIPS: Loongson 3: Add IRQ init and dispatch support Huacai Chen
2014-01-08 22:58   ` Aurelien Jarno
2014-01-09 12:52   ` Alex Smith
2014-01-09 12:52     ` Alex Smith
2014-01-08  2:44 ` [PATCH V16 07/12] MIPS: Loongson 3: Add serial port support Huacai Chen
2014-01-08 22:58   ` Aurelien Jarno
2014-01-08  2:44 ` [PATCH V16 08/12] MIPS: Loongson: Add swiotlb to support big memory (>4GB) Huacai Chen
2014-01-08 22:58   ` Aurelien Jarno
     [not found]     ` <CAAhV-H4h43N2OR4znwVv3miVbGkWJLapdgr9Jou1j4R8-9TRyA@mail.gmail.com>
2014-01-09 22:08       ` Aurelien Jarno
     [not found]         ` <CAAhV-H7WFdt-4jYG5qPV36UWJQnSfkSa2J-3CAs2+QLqwHVhuA@mail.gmail.com>
2014-01-11 15:24           ` Aurelien Jarno
2014-01-09 12:56   ` Alex Smith
2014-01-09 12:56     ` Alex Smith
     [not found]     ` <CAAhV-H7ZO0gNzQ5wQ-yD=NiP2AJrc3-bWLXHo-HDngf27c9+gQ@mail.gmail.com>
2014-01-11 15:25       ` Aurelien Jarno
2014-01-12  9:12         ` Huacai Chen
2014-01-12  9:57           ` Aurelien Jarno
2014-01-08  2:44 ` [PATCH V16 09/12] MIPS: Loongson: Add Loongson-3 Kconfig options Huacai Chen
2014-01-09 13:07   ` Alex Smith
2014-01-09 13:07     ` Alex Smith
2014-01-11 15:24     ` Aurelien Jarno
2014-01-13  3:02       ` Huacai Chen
2014-01-13  4:30         ` Aurelien Jarno
2014-01-13 10:15           ` Huacai Chen
2014-01-13 10:38             ` Aurelien Jarno
2014-01-13 12:15               ` Huacai Chen
2014-01-08  2:44 ` [PATCH V16 10/12] MIPS: Loongson 3: Add Loongson-3 SMP support Huacai Chen
2014-01-09 13:19   ` Alex Smith
2014-01-09 13:19     ` Alex Smith
2014-01-08  2:44 ` [PATCH V16 11/12] MIPS: Loongson 3: Add CPU hotplug support Huacai Chen
2014-01-11 15:24   ` Aurelien Jarno
2014-01-08  2:44 ` [PATCH V16 12/12] MIPS: Loongson: Add a Loongson-3 default config file Huacai Chen
2014-01-08  7:26 ` [PATCH V16 00/12] MIPS: Add Loongson-3 based machines support John Crispin
2014-01-18  9:38 ` Andreas Barth
     [not found]   ` <0466fa9d60b91233d2157d5ce0b51333.squirrel@mail.lemote.com>
2014-02-06 23:27     ` Andreas Barth

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.