linux-mips.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] MIPS: Loongson: Add CFUCFG&CSR support
@ 2019-09-01  7:49 Huacai Chen
  2019-09-01  7:49 ` [PATCH 2/3] MIPS: Loongson: Add Loongson-3A R4 basic support Huacai Chen
  0 siblings, 1 reply; 5+ messages in thread
From: Huacai Chen @ 2019-09-01  7:49 UTC (permalink / raw)
  To: Paul Burton, Ralf Baechle, James Hogan
  Cc: linux-mips, linux-mips, Fuxin Zhang, Zhangjin Wu, Huacai Chen,
	Huacai Chen, Jiaxun Yang

Loongson-3A R4+ (Loongson-3A4000 and newer) has CPUCFG (CPU config) and
CSR (Control and Status Register) extensions. This patch add read/write
functionalities for them.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 .../include/asm/mach-loongson64/loongson_regs.h    | 227 +++++++++++++++++++++
 1 file changed, 227 insertions(+)
 create mode 100644 arch/mips/include/asm/mach-loongson64/loongson_regs.h

diff --git a/arch/mips/include/asm/mach-loongson64/loongson_regs.h b/arch/mips/include/asm/mach-loongson64/loongson_regs.h
new file mode 100644
index 0000000..6e3569a
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson64/loongson_regs.h
@@ -0,0 +1,227 @@
+/*
+ * Read/Write Loongson Extension Registers
+ */
+
+#ifndef _LOONGSON_REGS_H_
+#define _LOONGSON_REGS_H_
+
+#include <linux/types.h>
+#include <linux/bits.h>
+
+#include <asm/mipsregs.h>
+#include <asm/cpu.h>
+
+static inline bool cpu_has_cfg(void)
+{
+	return ((read_c0_prid() & PRID_IMP_MASK) == PRID_IMP_LOONGSON_64G);
+}
+
+static inline u32 read_cpucfg(u32 reg)
+{
+	u32 __res;
+
+	__asm__ __volatile__(
+		"parse_r __res,%0\n\t"
+		"parse_r reg,%1\n\t"
+		".insn \n\t"
+		".word (0xc8080118 | (reg << 21) | (__res << 11))\n\t"
+		:"=r"(__res)
+		:"r"(reg)
+		:
+		);
+	return __res;
+}
+
+/* Bit Domains for CFG registers */
+#define LOONGSON_CFG0	0x0
+#define LOONGSON_CFG0_PRID GENMASK(31, 0)
+
+#define LOONGSON_CFG1 0x1
+#define LOONGSON_CFG1_FP	BIT(0)
+#define LOONGSON_CFG1_FPREV	GENMASK(3, 1)
+#define LOONGSON_CFG1_MMI	BIT(4)
+#define LOONGSON_CFG1_MSA1	BIT(5)
+#define LOONGSON_CFG1_MSA2	BIT(6)
+#define LOONGSON_CFG1_CGP	BIT(7)
+#define LOONGSON_CFG1_WRP	BIT(8)
+#define LOONGSON_CFG1_LSX1	BIT(9)
+#define LOONGSON_CFG1_LSX2	BIT(10)
+#define LOONGSON_CFG1_LASX	BIT(11)
+#define LOONGSON_CFG1_R6FXP	BIT(12)
+#define LOONGSON_CFG1_R6CRCP	BIT(13)
+#define LOONGSON_CFG1_R6FPP	BIT(14)
+#define LOONGSON_CFG1_CNT64	BIT(15)
+#define LOONGSON_CFG1_LSLDR0	BIT(16)
+#define LOONGSON_CFG1_LSPREF	BIT(17)
+#define LOONGSON_CFG1_LSPREFX	BIT(18)
+#define LOONGSON_CFG1_LSSYNCI	BIT(19)
+#define LOONGSON_CFG1_LSUCA	BIT(20)
+#define LOONGSON_CFG1_LLSYNC	BIT(21)
+#define LOONGSON_CFG1_TGTSYNC	BIT(22)
+#define LOONGSON_CFG1_LLEXC	BIT(23)
+#define LOONGSON_CFG1_SCRAND	BIT(24)
+#define LOONGSON_CFG1_MUALP	BIT(25)
+#define LOONGSON_CFG1_KMUALEN	BIT(26)
+#define LOONGSON_CFG1_ITLBT	BIT(27)
+#define LOONGSON_CFG1_LSUPERF	BIT(28)
+#define LOONGSON_CFG1_SFBP	BIT(29)
+#define LOONGSON_CFG1_CDMAP	BIT(30)
+
+#define LOONGSON_CFG2 0x2
+#define LOONGSON_CFG2_LEXT1	BIT(0)
+#define LOONGSON_CFG2_LEXT2	BIT(1)
+#define LOONGSON_CFG2_LEXT3	BIT(2)
+#define LOONGSON_CFG2_LSPW	BIT(3)
+#define LOONGSON_CFG2_LBT1	BIT(4)
+#define LOONGSON_CFG2_LBT2	BIT(5)
+#define LOONGSON_CFG2_LBT3	BIT(6)
+#define LOONGSON_CFG2_LBTMMU	BIT(7)
+#define LOONGSON_CFG2_LPMP	BIT(8)
+#define LOONGSON_CFG2_LPMPREV	GENMASK(11, 9)
+#define LOONGSON_CFG2_LAMO	BIT(12)
+#define LOONGSON_CFG2_LPIXU	BIT(13)
+#define LOONGSON_CFG2_LPIXUN	BIT(14)
+#define LOONGSON_CFG2_LZVP	BIT(15)
+#define LOONGSON_CFG2_LZVREV	GENMASK(18, 16)
+#define LOONGSON_CFG2_LGFTP	BIT(19)
+#define LOONGSON_CFG2_LGFTPREV	GENMASK(22, 20)
+#define LOONGSON_CFG2_LLFTP	BIT(23)
+#define LOONGSON_CFG2_LLFTPREV	GENMASK(24, 26)
+#define LOONGSON_CFG2_LCSRP	BIT(27)
+#define LOONGSON_CFG2_LDISBLIKELY	BIT(28)
+
+#define LOONGSON_CFG3 0x3
+#define LOONGSON_CFG3_LCAMP	BIT(0)
+#define LOONGSON_CFG3_LCAMREV	GENMASK(3, 1)
+#define LOONGSON_CFG3_LCAMNUM	GENMASK(11, 4)
+#define LOONGSON_CFG3_LCAMKW	GENMASK(19, 12)
+#define LOONGSON_CFG3_LCAMVW	GENMASK(27, 20)
+
+#define LOONGSON_CFG4 0x4
+#define LOONGSON_CFG4_CCFREQ	GENMASK(31, 0)
+
+#define LOONGSON_CFG5 0x5
+#define LOONGSON_CFG5_CFM	GENMASK(15, 0)
+#define LOONGSON_CFG5_CFD	GENMASK(31, 16)
+
+#define LOONGSON_CFG6 0x6
+
+#define LOONGSON_CFG7 0x7
+#define LOONGSON_CFG7_GCCAEQRP	BIT(0)
+#define LOONGSON_CFG7_UCAWINP	BIT(1)
+
+static inline bool cpu_has_csr(void)
+{
+	if (cpu_has_cfg())
+		return (read_cpucfg(LOONGSON_CFG2) & LOONGSON_CFG2_LCSRP);
+
+	return false;
+}
+
+static inline u32 csr_readl(u32 reg)
+{
+	u32 __res;
+
+	/* RDCSR reg, val */
+	__asm__ __volatile__(
+		"parse_r __res,%0\n\t"
+		"parse_r reg,%1\n\t"
+		".insn \n\t"
+		".word (0xc8000118 | (reg << 21) | (__res << 11))\n\t"
+		:"=r"(__res)
+		:"r"(reg)
+		:
+		);
+	return __res;
+}
+
+static inline u64 csr_readq(u32 reg)
+{
+	u64 __res;
+
+	/* DWRCSR reg, val */
+	__asm__ __volatile__(
+		"parse_r __res,%0\n\t"
+		"parse_r reg,%1\n\t"
+		".insn \n\t"
+		".word (0xc8020118 | (reg << 21) | (__res << 11))\n\t"
+		:"=r"(__res)
+		:"r"(reg)
+		:
+		);
+	return __res;
+}
+
+static inline void csr_writel(u32 val, u32 reg)
+{
+	/* WRCSR reg, val */
+	__asm__ __volatile__(
+		"parse_r reg,%0\n\t"
+		"parse_r val,%1\n\t"
+		".insn \n\t"
+		".word (0xc8010118 | (reg << 21) | (val << 11))\n\t"
+		:
+		:"r"(reg),"r"(val)
+		:
+		);
+}
+
+static inline void csr_writeq(u64 val, u32 reg)
+{
+	/* DWRCSR reg, val */
+	__asm__ __volatile__(
+		"parse_r reg,%0\n\t"
+		"parse_r val,%1\n\t"
+		".insn \n\t"
+		".word (0xc8030118 | (reg << 21) | (val << 11))\n\t"
+		:
+		:"r"(reg),"r"(val)
+		:
+		);
+}
+
+/* Public CSR Register can also be accessed with regular addresses */
+#define CSR_PUBLIC_MMIO_BASE 0x1fe00000
+
+#define MMIO_CSR(x)		(void *)TO_UNCAC(CSR_PUBLIC_MMIO_BASE + x)
+
+#define LOONGSON_CSR_FEATURES	0x8
+#define LOONGSON_CSRF_TEMP	BIT(0)
+#define LOONGSON_CSRF_NODECNT	BIT(1)
+#define LOONGSON_CSRF_MSI	BIT(2)
+#define LOONGSON_CSRF_EXTIOI	BIT(3)
+#define LOONGSON_CSRF_IPI	BIT(4)
+#define LOONGSON_CSRF_FREQ	BIT(5)
+
+#define LOONGSON_CSR_VENDOR	0x10 /* Vendor name string, should be "Loongson" */
+#define LOONGSON_CSR_CPUNAME	0x20 /* Processor name string */
+#define LOONGSON_CSR_NODECNT	0x408
+#define LOONGSON_CSR_CPUTEMP	0x428
+
+/* PerCore CSR, only accessable by local cores */
+#define LOONGSON_CSR_IPI_STATUS	0x1000
+#define LOONGSON_CSR_IPI_EN	0x1004
+#define LOONGSON_CSR_IPI_SET	0x1008
+#define LOONGSON_CSR_IPI_CLEAR	0x100c
+#define LOONGSON_CSR_IPI_SEND	0x1040
+#define CSR_IPI_SEND_IP_SHIFT	0
+#define CSR_IPI_SEND_CPU_SHIFT	16
+#define CSR_IPI_SEND_BLOCK	BIT(31)
+
+static inline u64 drdtime(void)
+{
+	int rID = 0;
+	u64 val = 0;
+
+	__asm__ __volatile__(
+		"parse_r rID,%0\n\t"
+		"parse_r val,%1\n\t"
+		".insn \n\t"
+		".word (0xc8090118 | (rID << 21) | (val << 11))\n\t"
+		:"=r"(rID),"=r"(val)
+		:
+		);
+	return val;
+}
+
+#endif
-- 
2.7.0


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

* [PATCH 2/3] MIPS: Loongson: Add Loongson-3A R4 basic support
  2019-09-01  7:49 [PATCH 1/3] MIPS: Loongson: Add CFUCFG&CSR support Huacai Chen
@ 2019-09-01  7:49 ` Huacai Chen
  2019-09-03  6:39   ` Jiaxun Yang
  0 siblings, 1 reply; 5+ messages in thread
From: Huacai Chen @ 2019-09-01  7:49 UTC (permalink / raw)
  To: Paul Burton, Ralf Baechle, James Hogan
  Cc: linux-mips, linux-mips, Fuxin Zhang, Zhangjin Wu, Huacai Chen,
	Huacai Chen, Jiaxun Yang

All Loongson-3 CPU family:

Code-name         Brand-name       PRId
Loongson-3A R1    Loongson-3A1000  0x6305
Loongson-3A R2    Loongson-3A2000  0x6308
Loongson-3A R2.1  Loongson-3A2000  0x630c
Loongson-3A R3    Loongson-3A3000  0x6309
Loongson-3A R3.1  Loongson-3A3000  0x630d
Loongson-3A R4    Loongson-3A4000  0xc000
Loongson-3B R1    Loongson-3B1000  0x6306
Loongson-3B R2    Loongson-3B1500  0x6307

Features of R4 revision of Loongson-3A:

  - All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
  - Support variable ASID bits.
  - Support MSA and VZ extensions.
  - Support CPUCFG (CPU config) and CSR (Control and Status Register)
      extensions.
  - 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
      set-associative).

Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/Kconfig                                  |  2 +
 arch/mips/include/asm/cpu.h                        |  4 +-
 .../asm/mach-loongson64/kernel-entry-init.h        | 28 +++++--
 arch/mips/kernel/cpu-probe.c                       | 15 +++-
 arch/mips/kernel/idle.c                            |  3 +-
 arch/mips/loongson64/loongson-3/smp.c              | 90 ++++++++++++----------
 arch/mips/mm/c-r4k.c                               |  3 +-
 drivers/platform/mips/cpu_hwmon.c                  | 14 +++-
 8 files changed, 107 insertions(+), 52 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 31c7044..3afcbce 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1378,9 +1378,11 @@ config CPU_LOONGSON3
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
 	select CPU_SUPPORTS_HUGEPAGES
+	select CPU_SUPPORTS_MSA
 	select CPU_HAS_LOAD_STORE_LR
 	select WEAK_ORDERING
 	select WEAK_REORDERING_BEYOND_LLSC
+	select MIPS_ASID_BITS_VARIABLE
 	select MIPS_PGD_C0_CONTEXT
 	select MIPS_L1_CACHE_SHIFT_6
 	select GPIOLIB
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 7fddcb8..81ddb57 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -91,7 +91,9 @@
 #define PRID_IMP_LOONGSON_32	0x4200  /* Loongson-1 */
 #define PRID_IMP_R5432		0x5400
 #define PRID_IMP_R5500		0x5500
-#define PRID_IMP_LOONGSON_64	0x6300  /* Loongson-2/3 */
+#define PRID_IMP_LOONGSON_64R	0x6100  /* Reduced Loongson-2 */
+#define PRID_IMP_LOONGSON_64C	0x6300  /* Classic Loongson-2 and Loongson-3 */
+#define PRID_IMP_LOONGSON_64G	0xc000  /* Generic Loongson-2 and Loongson-3 */
 
 #define PRID_IMP_UNKNOWN	0xff00
 
diff --git a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
index b5e288a..b968732 100644
--- a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
+++ b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
@@ -30,13 +30,21 @@
 	mtc0	t0, CP0_PAGEGRAIN
 	/* Enable STFill Buffer */
 	mfc0	t0, CP0_PRID
+	/* Loongson-3A R4+ */
+	andi	t1, t0, PRID_IMP_MASK
+	li	t2, PRID_IMP_LOONGSON_64G
+	beq     t1, t2, 1f
+	nop
+	/* Loongson-3A R2/R3 */
 	andi	t0, (PRID_IMP_MASK | PRID_REV_MASK)
-	slti	t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2_0)
-	bnez	t0, 1f
+	slti	t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0)
+	bnez	t0, 2f
+	nop
+1:
 	mfc0	t0, CP0_CONFIG6
 	or	t0, 0x100
 	mtc0	t0, CP0_CONFIG6
-1:
+2:
 	_ehb
 	.set	pop
 #endif
@@ -59,13 +67,21 @@
 	mtc0	t0, CP0_PAGEGRAIN
 	/* Enable STFill Buffer */
 	mfc0	t0, CP0_PRID
+	/* Loongson-3A R4+ */
+	andi	t1, t0, PRID_IMP_MASK
+	li	t2, PRID_IMP_LOONGSON_64G
+	beq     t1, t2, 1f
+	nop
+	/* Loongson-3A R2/R3 */
 	andi	t0, (PRID_IMP_MASK | PRID_REV_MASK)
-	slti	t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2_0)
-	bnez	t0, 1f
+	slti	t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0)
+	bnez	t0, 2f
+	nop
+1:
 	mfc0	t0, CP0_CONFIG6
 	or	t0, 0x100
 	mtc0	t0, CP0_CONFIG6
-1:
+2:
 	_ehb
 	.set	pop
 #endif
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index c2eb392..09b2c67 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -1526,7 +1526,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
 			     MIPS_CPU_LLSC | MIPS_CPU_BP_GHIST;
 		c->tlbsize = 64;
 		break;
-	case PRID_IMP_LOONGSON_64:  /* Loongson-2/3 */
+	case PRID_IMP_LOONGSON_64C:  /* Loongson-2/3 */
 		switch (c->processor_id & PRID_REV_MASK) {
 		case PRID_REV_LOONGSON2E:
 			c->cputype = CPU_LOONGSON2;
@@ -1903,7 +1903,7 @@ static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
 static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
 {
 	switch (c->processor_id & PRID_IMP_MASK) {
-	case PRID_IMP_LOONGSON_64:  /* Loongson-2/3 */
+	case PRID_IMP_LOONGSON_64C:  /* Loongson-2/3 */
 		switch (c->processor_id & PRID_REV_MASK) {
 		case PRID_REV_LOONGSON3A_R2_0:
 		case PRID_REV_LOONGSON3A_R2_1:
@@ -1927,6 +1927,17 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
 		c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
 			MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
 		break;
+	case PRID_IMP_LOONGSON_64G:
+		c->cputype = CPU_LOONGSON3;
+		__cpu_name[cpu] = "ICT Loongson-3";
+		set_elf_platform(cpu, "loongson3a");
+		set_isa(c, MIPS_CPU_ISA_M64R2);
+		decode_configs(c);
+		c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE;
+		c->writecombine = _CACHE_UNCACHED_ACCELERATED;
+		c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
+			MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
+		break;
 	default:
 		panic("Unknown Loongson Processor ID!");
 		break;
diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
index eb2afc0..980d6c3 100644
--- a/arch/mips/kernel/idle.c
+++ b/arch/mips/kernel/idle.c
@@ -179,7 +179,8 @@ void __init check_wait(void)
 		cpu_wait = r4k_wait;
 		break;
 	case CPU_LOONGSON3:
-		if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2_0)
+		if ((c->processor_id & (PRID_IMP_MASK | PRID_REV_MASK)) >=
+				(PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0))
 			cpu_wait = r4k_wait;
 		break;
 
diff --git a/arch/mips/loongson64/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c
index ce68cda..e999bb1 100644
--- a/arch/mips/loongson64/loongson-3/smp.c
+++ b/arch/mips/loongson64/loongson-3/smp.c
@@ -450,7 +450,7 @@ static void loongson3_cpu_die(unsigned int cpu)
  * 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) */
-static void loongson3a_r1_play_dead(int *state_addr)
+static void loongson3_type1_play_dead(int *state_addr)
 {
 	register int val;
 	register long cpuid, core, node, count;
@@ -512,7 +512,7 @@ static void loongson3a_r1_play_dead(int *state_addr)
 		: "a1");
 }
 
-static void loongson3a_r2r3_play_dead(int *state_addr)
+static void loongson3_type2_play_dead(int *state_addr)
 {
 	register int val;
 	register long cpuid, core, node, count;
@@ -532,27 +532,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
 		"   cache 1, 3(%[addr])           \n"
 		"   addiu %[sets], %[sets], -1    \n"
 		"   bnez  %[sets], 1b             \n"
-		"   addiu %[addr], %[addr], 0x40  \n"
-		"   li %[addr], 0x80000000        \n" /* KSEG0 */
-		"2: cache 2, 0(%[addr])           \n" /* flush L1 VCache */
-		"   cache 2, 1(%[addr])           \n"
-		"   cache 2, 2(%[addr])           \n"
-		"   cache 2, 3(%[addr])           \n"
-		"   cache 2, 4(%[addr])           \n"
-		"   cache 2, 5(%[addr])           \n"
-		"   cache 2, 6(%[addr])           \n"
-		"   cache 2, 7(%[addr])           \n"
-		"   cache 2, 8(%[addr])           \n"
-		"   cache 2, 9(%[addr])           \n"
-		"   cache 2, 10(%[addr])          \n"
-		"   cache 2, 11(%[addr])          \n"
-		"   cache 2, 12(%[addr])          \n"
-		"   cache 2, 13(%[addr])          \n"
-		"   cache 2, 14(%[addr])          \n"
-		"   cache 2, 15(%[addr])          \n"
-		"   addiu %[vsets], %[vsets], -1  \n"
-		"   bnez  %[vsets], 2b            \n"
-		"   addiu %[addr], %[addr], 0x40  \n"
+		"   addiu %[addr], %[addr], 0x20  \n"
 		"   li    %[val], 0x7             \n" /* *state_addr = CPU_DEAD; */
 		"   sw    %[val], (%[state_addr]) \n"
 		"   sync                          \n"
@@ -560,8 +540,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
 		"   .set pop                      \n"
 		: [addr] "=&r" (addr), [val] "=&r" (val)
 		: [state_addr] "r" (state_addr),
-		  [sets] "r" (cpu_data[smp_processor_id()].dcache.sets),
-		  [vsets] "r" (cpu_data[smp_processor_id()].vcache.sets));
+		  [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
 
 	__asm__ __volatile__(
 		"   .set push                         \n"
@@ -576,6 +555,8 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
 		"   andi  %[node], %[cpuid], 0xc      \n"
 		"   dsll  %[node], 42                 \n" /* get node id */
 		"   or    %[base], %[base], %[node]   \n"
+		"   dsrl  %[node], 30                 \n" /* 15:14 */
+		"   or    %[base], %[base], %[node]   \n"
 		"1: li    %[count], 0x100             \n" /* wait for init loop */
 		"2: bnez  %[count], 2b                \n" /* limit mailbox access */
 		"   addiu %[count], -1                \n"
@@ -595,7 +576,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
 		: "a1");
 }
 
-static void loongson3b_play_dead(int *state_addr)
+static void loongson3_type3_play_dead(int *state_addr)
 {
 	register int val;
 	register long cpuid, core, node, count;
@@ -615,7 +596,27 @@ static void loongson3b_play_dead(int *state_addr)
 		"   cache 1, 3(%[addr])           \n"
 		"   addiu %[sets], %[sets], -1    \n"
 		"   bnez  %[sets], 1b             \n"
-		"   addiu %[addr], %[addr], 0x20  \n"
+		"   addiu %[addr], %[addr], 0x40  \n"
+		"   li %[addr], 0x80000000        \n" /* KSEG0 */
+		"2: cache 2, 0(%[addr])           \n" /* flush L1 VCache */
+		"   cache 2, 1(%[addr])           \n"
+		"   cache 2, 2(%[addr])           \n"
+		"   cache 2, 3(%[addr])           \n"
+		"   cache 2, 4(%[addr])           \n"
+		"   cache 2, 5(%[addr])           \n"
+		"   cache 2, 6(%[addr])           \n"
+		"   cache 2, 7(%[addr])           \n"
+		"   cache 2, 8(%[addr])           \n"
+		"   cache 2, 9(%[addr])           \n"
+		"   cache 2, 10(%[addr])          \n"
+		"   cache 2, 11(%[addr])          \n"
+		"   cache 2, 12(%[addr])          \n"
+		"   cache 2, 13(%[addr])          \n"
+		"   cache 2, 14(%[addr])          \n"
+		"   cache 2, 15(%[addr])          \n"
+		"   addiu %[vsets], %[vsets], -1  \n"
+		"   bnez  %[vsets], 2b            \n"
+		"   addiu %[addr], %[addr], 0x40  \n"
 		"   li    %[val], 0x7             \n" /* *state_addr = CPU_DEAD; */
 		"   sw    %[val], (%[state_addr]) \n"
 		"   sync                          \n"
@@ -623,7 +624,8 @@ static void loongson3b_play_dead(int *state_addr)
 		"   .set pop                      \n"
 		: [addr] "=&r" (addr), [val] "=&r" (val)
 		: [state_addr] "r" (state_addr),
-		  [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
+		  [sets] "r" (cpu_data[smp_processor_id()].dcache.sets),
+		  [vsets] "r" (cpu_data[smp_processor_id()].vcache.sets));
 
 	__asm__ __volatile__(
 		"   .set push                         \n"
@@ -638,8 +640,6 @@ static void loongson3b_play_dead(int *state_addr)
 		"   andi  %[node], %[cpuid], 0xc      \n"
 		"   dsll  %[node], 42                 \n" /* get node id */
 		"   or    %[base], %[base], %[node]   \n"
-		"   dsrl  %[node], 30                 \n" /* 15:14 */
-		"   or    %[base], %[base], %[node]   \n"
 		"1: li    %[count], 0x100             \n" /* wait for init loop */
 		"2: bnez  %[count], 2b                \n" /* limit mailbox access */
 		"   addiu %[count], -1                \n"
@@ -661,30 +661,42 @@ static void loongson3b_play_dead(int *state_addr)
 
 void play_dead(void)
 {
-	int *state_addr;
+	int prid_imp, prid_rev, *state_addr;
 	unsigned int cpu = smp_processor_id();
 	void (*play_dead_at_ckseg1)(int *);
 
 	idle_task_exit();
-	switch (read_c0_prid() & PRID_REV_MASK) {
+
+	prid_imp = read_c0_prid() & PRID_IMP_MASK;
+	prid_rev = read_c0_prid() & PRID_REV_MASK;
+
+	if (prid_imp == PRID_IMP_LOONGSON_64G) {
+		play_dead_at_ckseg1 =
+			(void *)CKSEG1ADDR((unsigned long)loongson3_type3_play_dead);
+		goto out;
+	}
+
+	switch (prid_rev) {
 	case PRID_REV_LOONGSON3A_R1:
 	default:
 		play_dead_at_ckseg1 =
-			(void *)CKSEG1ADDR((unsigned long)loongson3a_r1_play_dead);
+			(void *)CKSEG1ADDR((unsigned long)loongson3_type1_play_dead);
+		break;
+	case PRID_REV_LOONGSON3B_R1:
+	case PRID_REV_LOONGSON3B_R2:
+		play_dead_at_ckseg1 =
+			(void *)CKSEG1ADDR((unsigned long)loongson3_type2_play_dead);
 		break;
 	case PRID_REV_LOONGSON3A_R2_0:
 	case PRID_REV_LOONGSON3A_R2_1:
 	case PRID_REV_LOONGSON3A_R3_0:
 	case PRID_REV_LOONGSON3A_R3_1:
 		play_dead_at_ckseg1 =
-			(void *)CKSEG1ADDR((unsigned long)loongson3a_r2r3_play_dead);
-		break;
-	case PRID_REV_LOONGSON3B_R1:
-	case PRID_REV_LOONGSON3B_R2:
-		play_dead_at_ckseg1 =
-			(void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
+			(void *)CKSEG1ADDR((unsigned long)loongson3_type3_play_dead);
 		break;
 	}
+
+out:
 	state_addr = &per_cpu(cpu_state, cpu);
 	mb();
 	play_dead_at_ckseg1(state_addr);
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 89b9c85..4bf9906 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1267,7 +1267,8 @@ static void probe_pcache(void)
 					  c->dcache.ways *
 					  c->dcache.linesz;
 		c->dcache.waybit = 0;
-		if ((prid & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2_0)
+		if ((c->processor_id & (PRID_IMP_MASK | PRID_REV_MASK)) >=
+				(PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0))
 			c->options |= MIPS_CPU_PREFETCH;
 		break;
 
diff --git a/drivers/platform/mips/cpu_hwmon.c b/drivers/platform/mips/cpu_hwmon.c
index a7f184b..15ca8bf 100644
--- a/drivers/platform/mips/cpu_hwmon.c
+++ b/drivers/platform/mips/cpu_hwmon.c
@@ -9,6 +9,7 @@
 #include <loongson.h>
 #include <boot_param.h>
 #include <loongson_hwmon.h>
+#include <loongson_regs.h>
 
 /*
  * Loongson-3 series cpu has two sensors inside,
@@ -18,10 +19,17 @@
  */
 int loongson3_cpu_temp(int cpu)
 {
-	u32 reg, prid_rev;
+	u32 reg, prid_imp, prid_rev;
 
-	reg = LOONGSON_CHIPTEMP(cpu);
+	prid_imp = read_c0_prid() & PRID_IMP_MASK;
 	prid_rev = read_c0_prid() & PRID_REV_MASK;
+
+	if(prid_imp == PRID_IMP_LOONGSON_64G) {
+		reg = (csr_readl(LOONGSON_CSR_CPUTEMP) & 0xff);
+		goto out;
+	}
+
+	reg = LOONGSON_CHIPTEMP(cpu);
 	switch (prid_rev) {
 	case PRID_REV_LOONGSON3A_R1:
 		reg = (reg >> 8) & 0xff;
@@ -37,6 +45,8 @@ int loongson3_cpu_temp(int cpu)
 		reg = (reg & 0xffff)*731/0x4000 - 273;
 		break;
 	}
+
+out:
 	return (int)reg * 1000;
 }
 
-- 
2.7.0


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

* Re: [PATCH 2/3] MIPS: Loongson: Add Loongson-3A R4 basic support
  2019-09-01  7:49 ` [PATCH 2/3] MIPS: Loongson: Add Loongson-3A R4 basic support Huacai Chen
@ 2019-09-03  6:39   ` Jiaxun Yang
  2019-09-04  3:43     ` Huacai Chen
  0 siblings, 1 reply; 5+ messages in thread
From: Jiaxun Yang @ 2019-09-03  6:39 UTC (permalink / raw)
  To: Huacai Chen, Paul Burton, Ralf Baechle, James Hogan
  Cc: linux-mips, linux-mips, Fuxin Zhang, Zhangjin Wu, Huacai Chen


在 2019/9/1 15:49, Huacai Chen 写道:
> All Loongson-3 CPU family:
>
> Code-name         Brand-name       PRId
> Loongson-3A R1    Loongson-3A1000  0x6305
> Loongson-3A R2    Loongson-3A2000  0x6308
> Loongson-3A R2.1  Loongson-3A2000  0x630c
> Loongson-3A R3    Loongson-3A3000  0x6309
> Loongson-3A R3.1  Loongson-3A3000  0x630d
> Loongson-3A R4    Loongson-3A4000  0xc000
> Loongson-3B R1    Loongson-3B1000  0x6306
> Loongson-3B R2    Loongson-3B1500  0x6307
>
> Features of R4 revision of Loongson-3A:
>
>    - All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
>    - Support variable ASID bits.
>    - Support MSA and VZ extensions.
>    - Support CPUCFG (CPU config) and CSR (Control and Status Register)
>        extensions.
>    - 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
>        set-associative).
>
> Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
> the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
> 2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
> which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
> (e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
> general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>   arch/mips/Kconfig                                  |  2 +
>   arch/mips/include/asm/cpu.h                        |  4 +-
>   .../asm/mach-loongson64/kernel-entry-init.h        | 28 +++++--
>   arch/mips/kernel/cpu-probe.c                       | 15 +++-
>   arch/mips/kernel/idle.c                            |  3 +-
>   arch/mips/loongson64/loongson-3/smp.c              | 90 ++++++++++++----------
>   arch/mips/mm/c-r4k.c                               |  3 +-
>   drivers/platform/mips/cpu_hwmon.c                  | 14 +++-
>   8 files changed, 107 insertions(+), 52 deletions(-)
>
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index 31c7044..3afcbce 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -1378,9 +1378,11 @@ config CPU_LOONGSON3
>   	select CPU_SUPPORTS_64BIT_KERNEL
>   	select CPU_SUPPORTS_HIGHMEM
>   	select CPU_SUPPORTS_HUGEPAGES
> +	select CPU_SUPPORTS_MSA
>   	select CPU_HAS_LOAD_STORE_LR
>   	select WEAK_ORDERING
>   	select WEAK_REORDERING_BEYOND_LLSC
> +	select MIPS_ASID_BITS_VARIABLE
>   	select MIPS_PGD_C0_CONTEXT
>   	select MIPS_L1_CACHE_SHIFT_6
>   	select GPIOLIB
> diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
> index 7fddcb8..81ddb57 100644
> --- a/arch/mips/include/asm/cpu.h
> +++ b/arch/mips/include/asm/cpu.h
> @@ -91,7 +91,9 @@
>   #define PRID_IMP_LOONGSON_32	0x4200  /* Loongson-1 */
>   #define PRID_IMP_R5432		0x5400
>   #define PRID_IMP_R5500		0x5500
> -#define PRID_IMP_LOONGSON_64	0x6300  /* Loongson-2/3 */
> +#define PRID_IMP_LOONGSON_64R	0x6100  /* Reduced Loongson-2 */
> +#define PRID_IMP_LOONGSON_64C	0x6300  /* Classic Loongson-2 and Loongson-3 */
> +#define PRID_IMP_LOONGSON_64G	0xc000  /* Generic Loongson-2 and Loongson-3 */
>   
>   #define PRID_IMP_UNKNOWN	0xff00
>   
> diff --git a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
> index b5e288a..b968732 100644
> --- a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
> +++ b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
> @@ -30,13 +30,21 @@
>   	mtc0	t0, CP0_PAGEGRAIN
>   	/* Enable STFill Buffer */
>   	mfc0	t0, CP0_PRID
> +	/* Loongson-3A R4+ */

Hi Huacai,

For 3A R4+, Firmware will take care of SFB switch according tu Ruiyang 
Wu, the chief architect's words, are we still going to do that?

> +	andi	t1, t0, PRID_IMP_MASK
> +	li	t2, PRID_IMP_LOONGSON_64G
> +	beq     t1, t2, 1f
> +	nop
> +	/* Loongson-3A R2/R3 */
>   	andi	t0, (PRID_IMP_MASK | PRID_REV_MASK)
> -	slti	t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2_0)
> -	bnez	t0, 1f
> +	slti	t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0)
> +	bnez	t0, 2f
> +	nop
> +1:
>   	mfc0	t0, CP0_CONFIG6
>   	or	t0, 0x100
>   	mtc0	t0, CP0_CONFIG6
> -1:
> +2:
>   	_ehb
>   	.set	pop
>   #endif
> @@ -59,13 +67,21 @@
>   	mtc0	t0, CP0_PAGEGRAIN
>   	/* Enable STFill Buffer */
>   	mfc0	t0, CP0_PRID
> +	/* Loongson-3A R4+ */
> +	andi	t1, t0, PRID_IMP_MASK
> +	li	t2, PRID_IMP_LOONGSON_64G
> +	beq     t1, t2, 1f
> +	nop
The same.
> +	/* Loongson-3A R2/R3 */
>   	andi	t0, (PRID_IMP_MASK | PRID_REV_MASK)
> -	slti	t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2_0)
> -	bnez	t0, 1f
> +	slti	t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0)
> +	bnez	t0, 2f
> +	nop
> +1:
>   	mfc0	t0, CP0_CONFIG6
>   	or	t0, 0x100
>   	mtc0	t0, CP0_CONFIG6
> -1:
> +2:
>   	_ehb
>   	.set	pop
>   #endif
> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> index c2eb392..09b2c67 100644
> --- a/arch/mips/kernel/cpu-probe.c
> +++ b/arch/mips/kernel/cpu-probe.c
> @@ -1526,7 +1526,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
>   			     MIPS_CPU_LLSC | MIPS_CPU_BP_GHIST;
>   		c->tlbsize = 64;
>   		break;
> -	case PRID_IMP_LOONGSON_64:  /* Loongson-2/3 */
> +	case PRID_IMP_LOONGSON_64C:  /* Loongson-2/3 */
>   		switch (c->processor_id & PRID_REV_MASK) {
>   		case PRID_REV_LOONGSON2E:
>   			c->cputype = CPU_LOONGSON2;
> @@ -1903,7 +1903,7 @@ static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
>   static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
>   {
>   	switch (c->processor_id & PRID_IMP_MASK) {
> -	case PRID_IMP_LOONGSON_64:  /* Loongson-2/3 */
> +	case PRID_IMP_LOONGSON_64C:  /* Loongson-2/3 */
>   		switch (c->processor_id & PRID_REV_MASK) {
>   		case PRID_REV_LOONGSON3A_R2_0:
>   		case PRID_REV_LOONGSON3A_R2_1:
> @@ -1927,6 +1927,17 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
>   		c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
>   			MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
>   		break;
> +	case PRID_IMP_LOONGSON_64G:
> +		c->cputype = CPU_LOONGSON3;
> +		__cpu_name[cpu] = "ICT Loongson-3";
> +		set_elf_platform(cpu, "loongson3a");
> +		set_isa(c, MIPS_CPU_ISA_M64R2);
> +		decode_configs(c);
> +		c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE;
CPUCFG Register have bits to mark these features (ASEs, UCA). As we 
would never know what features would next Loongson product have, we'd 
better probe features by CPUCFG rather than PRID.
> +		c->writecombine = _CACHE_UNCACHED_ACCELERATED;
> +		c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
> +			MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
> +		break;
>   	default:
>   		panic("Unknown Loongson Processor ID!");
>   		break;
> diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
> index eb2afc0..980d6c3 100644
> --- a/arch/mips/kernel/idle.c
> +++ b/arch/mips/kernel/idle.c
> @@ -179,7 +179,8 @@ void __init check_wait(void)
>   		cpu_wait = r4k_wait;
>   		break;
>   	case CPU_LOONGSON3:
> -		if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2_0)
> +		if ((c->processor_id & (PRID_IMP_MASK | PRID_REV_MASK)) >=
> +				(PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0))
>   			cpu_wait = r4k_wait;
The same. Probably we can have a Loongson feature flag in kernel to help 
with determining these features as PRID would never be a reliable way. 
As Yunqiang said, "I blame these Loongson guys here. Some Loongson guys 
is not so normal people. Anyway they are a little more normal now, and 
anyway again, still abnormal." You can never predict what will they do 
next. But the thing we can do is just reduce the cost of covering their 
next abnormal action in kernel.
>   		break;
>   
> diff --git a/arch/mips/loongson64/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c
> index ce68cda..e999bb1 100644
> --- a/arch/mips/loongson64/loongson-3/smp.c
> +++ b/arch/mips/loongson64/loongson-3/smp.c
> @@ -450,7 +450,7 @@ static void loongson3_cpu_die(unsigned int cpu)
>    * 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) */
> -static void loongson3a_r1_play_dead(int *state_addr)
> +static void loongson3_type1_play_dead(int *state_addr)
>   {
>   	register int val;
>   	register long cpuid, core, node, count;
> @@ -512,7 +512,7 @@ static void loongson3a_r1_play_dead(int *state_addr)
>   		: "a1");
>   }
>   
> -static void loongson3a_r2r3_play_dead(int *state_addr)
> +static void loongson3_type2_play_dead(int *state_addr)
>   {
>   	register int val;
>   	register long cpuid, core, node, count;
> @@ -532,27 +532,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
>   		"   cache 1, 3(%[addr])           \n"
>   		"   addiu %[sets], %[sets], -1    \n"
>   		"   bnez  %[sets], 1b             \n"
> -		"   addiu %[addr], %[addr], 0x40  \n"
> -		"   li %[addr], 0x80000000        \n" /* KSEG0 */
> -		"2: cache 2, 0(%[addr])           \n" /* flush L1 VCache */
> -		"   cache 2, 1(%[addr])           \n"
> -		"   cache 2, 2(%[addr])           \n"
> -		"   cache 2, 3(%[addr])           \n"
> -		"   cache 2, 4(%[addr])           \n"
> -		"   cache 2, 5(%[addr])           \n"
> -		"   cache 2, 6(%[addr])           \n"
> -		"   cache 2, 7(%[addr])           \n"
> -		"   cache 2, 8(%[addr])           \n"
> -		"   cache 2, 9(%[addr])           \n"
> -		"   cache 2, 10(%[addr])          \n"
> -		"   cache 2, 11(%[addr])          \n"
> -		"   cache 2, 12(%[addr])          \n"
> -		"   cache 2, 13(%[addr])          \n"
> -		"   cache 2, 14(%[addr])          \n"
> -		"   cache 2, 15(%[addr])          \n"
> -		"   addiu %[vsets], %[vsets], -1  \n"
> -		"   bnez  %[vsets], 2b            \n"
> -		"   addiu %[addr], %[addr], 0x40  \n"
> +		"   addiu %[addr], %[addr], 0x20  \n"
>   		"   li    %[val], 0x7             \n" /* *state_addr = CPU_DEAD; */
>   		"   sw    %[val], (%[state_addr]) \n"
>   		"   sync                          \n"
> @@ -560,8 +540,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
>   		"   .set pop                      \n"
>   		: [addr] "=&r" (addr), [val] "=&r" (val)
>   		: [state_addr] "r" (state_addr),
> -		  [sets] "r" (cpu_data[smp_processor_id()].dcache.sets),
> -		  [vsets] "r" (cpu_data[smp_processor_id()].vcache.sets));
> +		  [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
>   
>   	__asm__ __volatile__(
>   		"   .set push                         \n"
> @@ -576,6 +555,8 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
>   		"   andi  %[node], %[cpuid], 0xc      \n"
>   		"   dsll  %[node], 42                 \n" /* get node id */
>   		"   or    %[base], %[base], %[node]   \n"
> +		"   dsrl  %[node], 30                 \n" /* 15:14 */
> +		"   or    %[base], %[base], %[node]   \n"
>   		"1: li    %[count], 0x100             \n" /* wait for init loop */
>   		"2: bnez  %[count], 2b                \n" /* limit mailbox access */
>   		"   addiu %[count], -1                \n"
> @@ -595,7 +576,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
>   		: "a1");
>   }
>   
> -static void loongson3b_play_dead(int *state_addr)
> +static void loongson3_type3_play_dead(int *state_addr)
>   {
>   	register int val;
>   	register long cpuid, core, node, count;
> @@ -615,7 +596,27 @@ static void loongson3b_play_dead(int *state_addr)
>   		"   cache 1, 3(%[addr])           \n"
>   		"   addiu %[sets], %[sets], -1    \n"
>   		"   bnez  %[sets], 1b             \n"
> -		"   addiu %[addr], %[addr], 0x20  \n"
> +		"   addiu %[addr], %[addr], 0x40  \n"
> +		"   li %[addr], 0x80000000        \n" /* KSEG0 */
> +		"2: cache 2, 0(%[addr])           \n" /* flush L1 VCache */
> +		"   cache 2, 1(%[addr])           \n"
> +		"   cache 2, 2(%[addr])           \n"
> +		"   cache 2, 3(%[addr])           \n"
> +		"   cache 2, 4(%[addr])           \n"
> +		"   cache 2, 5(%[addr])           \n"
> +		"   cache 2, 6(%[addr])           \n"
> +		"   cache 2, 7(%[addr])           \n"
> +		"   cache 2, 8(%[addr])           \n"
> +		"   cache 2, 9(%[addr])           \n"
> +		"   cache 2, 10(%[addr])          \n"
> +		"   cache 2, 11(%[addr])          \n"
> +		"   cache 2, 12(%[addr])          \n"
> +		"   cache 2, 13(%[addr])          \n"
> +		"   cache 2, 14(%[addr])          \n"
> +		"   cache 2, 15(%[addr])          \n"
> +		"   addiu %[vsets], %[vsets], -1  \n"
> +		"   bnez  %[vsets], 2b            \n"
> +		"   addiu %[addr], %[addr], 0x40  \n"
>   		"   li    %[val], 0x7             \n" /* *state_addr = CPU_DEAD; */
>   		"   sw    %[val], (%[state_addr]) \n"
>   		"   sync                          \n"
> @@ -623,7 +624,8 @@ static void loongson3b_play_dead(int *state_addr)
>   		"   .set pop                      \n"
>   		: [addr] "=&r" (addr), [val] "=&r" (val)
>   		: [state_addr] "r" (state_addr),
> -		  [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
> +		  [sets] "r" (cpu_data[smp_processor_id()].dcache.sets),
> +		  [vsets] "r" (cpu_data[smp_processor_id()].vcache.sets));
>   
>   	__asm__ __volatile__(
>   		"   .set push                         \n"
> @@ -638,8 +640,6 @@ static void loongson3b_play_dead(int *state_addr)
>   		"   andi  %[node], %[cpuid], 0xc      \n"
>   		"   dsll  %[node], 42                 \n" /* get node id */
>   		"   or    %[base], %[base], %[node]   \n"
> -		"   dsrl  %[node], 30                 \n" /* 15:14 */
> -		"   or    %[base], %[base], %[node]   \n"
>   		"1: li    %[count], 0x100             \n" /* wait for init loop */
>   		"2: bnez  %[count], 2b                \n" /* limit mailbox access */
>   		"   addiu %[count], -1                \n"
> @@ -661,30 +661,42 @@ static void loongson3b_play_dead(int *state_addr)
>   
>   void play_dead(void)
>   {
> -	int *state_addr;
> +	int prid_imp, prid_rev, *state_addr;
>   	unsigned int cpu = smp_processor_id();
>   	void (*play_dead_at_ckseg1)(int *);
>   
>   	idle_task_exit();
> -	switch (read_c0_prid() & PRID_REV_MASK) {
> +
> +	prid_imp = read_c0_prid() & PRID_IMP_MASK;
> +	prid_rev = read_c0_prid() & PRID_REV_MASK;
> +
> +	if (prid_imp == PRID_IMP_LOONGSON_64G) {
> +		play_dead_at_ckseg1 =
> +			(void *)CKSEG1ADDR((unsigned long)loongson3_type3_play_dead);
> +		goto out;
> +	}
> +
> +	switch (prid_rev) {
>   	case PRID_REV_LOONGSON3A_R1:
>   	default:
>   		play_dead_at_ckseg1 =
> -			(void *)CKSEG1ADDR((unsigned long)loongson3a_r1_play_dead);
> +			(void *)CKSEG1ADDR((unsigned long)loongson3_type1_play_dead);
> +		break;
> +	case PRID_REV_LOONGSON3B_R1:
> +	case PRID_REV_LOONGSON3B_R2:
> +		play_dead_at_ckseg1 =
> +			(void *)CKSEG1ADDR((unsigned long)loongson3_type2_play_dead);
>   		break;
>   	case PRID_REV_LOONGSON3A_R2_0:
>   	case PRID_REV_LOONGSON3A_R2_1:
>   	case PRID_REV_LOONGSON3A_R3_0:
>   	case PRID_REV_LOONGSON3A_R3_1:
>   		play_dead_at_ckseg1 =
> -			(void *)CKSEG1ADDR((unsigned long)loongson3a_r2r3_play_dead);
> -		break;
> -	case PRID_REV_LOONGSON3B_R1:
> -	case PRID_REV_LOONGSON3B_R2:
> -		play_dead_at_ckseg1 =
> -			(void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
> +			(void *)CKSEG1ADDR((unsigned long)loongson3_type3_play_dead);
>   		break;
>   	}
> +
> +out:
>   	state_addr = &per_cpu(cpu_state, cpu);
>   	mb();
>   	play_dead_at_ckseg1(state_addr);

Things we're doing in playdead are mostly duplicated. Flushing cache, 
broadcasting CPU state, then doing loops to wait a mailbox PC. Probably 
we can reuse r4k cache ops here to avoid too much assembly. And reuse 
Mailbox loop code as they're almost the same.

--

Jiaxun Yang

> diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
> index 89b9c85..4bf9906 100644
> --- a/arch/mips/mm/c-r4k.c
> +++ b/arch/mips/mm/c-r4k.c
> @@ -1267,7 +1267,8 @@ static void probe_pcache(void)
>   					  c->dcache.ways *
>   					  c->dcache.linesz;
>   		c->dcache.waybit = 0;
> -		if ((prid & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2_0)
> +		if ((c->processor_id & (PRID_IMP_MASK | PRID_REV_MASK)) >=
> +				(PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0))
>   			c->options |= MIPS_CPU_PREFETCH;
>   		break;
>   
> diff --git a/drivers/platform/mips/cpu_hwmon.c b/drivers/platform/mips/cpu_hwmon.c
> index a7f184b..15ca8bf 100644
> --- a/drivers/platform/mips/cpu_hwmon.c
> +++ b/drivers/platform/mips/cpu_hwmon.c
> @@ -9,6 +9,7 @@
>   #include <loongson.h>
>   #include <boot_param.h>
>   #include <loongson_hwmon.h>
> +#include <loongson_regs.h>
>   
>   /*
>    * Loongson-3 series cpu has two sensors inside,
> @@ -18,10 +19,17 @@
>    */
>   int loongson3_cpu_temp(int cpu)
>   {
> -	u32 reg, prid_rev;
> +	u32 reg, prid_imp, prid_rev;
>   
> -	reg = LOONGSON_CHIPTEMP(cpu);
> +	prid_imp = read_c0_prid() & PRID_IMP_MASK;
>   	prid_rev = read_c0_prid() & PRID_REV_MASK;
> +
> +	if(prid_imp == PRID_IMP_LOONGSON_64G) {
> +		reg = (csr_readl(LOONGSON_CSR_CPUTEMP) & 0xff);
> +		goto out;
> +	}
> +
> +	reg = LOONGSON_CHIPTEMP(cpu);
>   	switch (prid_rev) {
>   	case PRID_REV_LOONGSON3A_R1:
>   		reg = (reg >> 8) & 0xff;
> @@ -37,6 +45,8 @@ int loongson3_cpu_temp(int cpu)
>   		reg = (reg & 0xffff)*731/0x4000 - 273;
>   		break;
>   	}
> +
> +out:
>   	return (int)reg * 1000;
>   }
>   

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

* Re: [PATCH 2/3] MIPS: Loongson: Add Loongson-3A R4 basic support
  2019-09-03  6:39   ` Jiaxun Yang
@ 2019-09-04  3:43     ` Huacai Chen
  2019-09-04  6:03       ` Jiaxun Yang
  0 siblings, 1 reply; 5+ messages in thread
From: Huacai Chen @ 2019-09-04  3:43 UTC (permalink / raw)
  To: Jiaxun Yang
  Cc: Paul Burton, Ralf Baechle, James Hogan, Linux MIPS Mailing List,
	open list:MIPS, Fuxin Zhang, Zhangjin Wu

On Tue, Sep 3, 2019 at 2:40 PM Jiaxun Yang <jiaxun.yang@flygoat.com> wrote:
>
>
> 在 2019/9/1 15:49, Huacai Chen 写道:
> > All Loongson-3 CPU family:
> >
> > Code-name         Brand-name       PRId
> > Loongson-3A R1    Loongson-3A1000  0x6305
> > Loongson-3A R2    Loongson-3A2000  0x6308
> > Loongson-3A R2.1  Loongson-3A2000  0x630c
> > Loongson-3A R3    Loongson-3A3000  0x6309
> > Loongson-3A R3.1  Loongson-3A3000  0x630d
> > Loongson-3A R4    Loongson-3A4000  0xc000
> > Loongson-3B R1    Loongson-3B1000  0x6306
> > Loongson-3B R2    Loongson-3B1500  0x6307
> >
> > Features of R4 revision of Loongson-3A:
> >
> >    - All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
> >    - Support variable ASID bits.
> >    - Support MSA and VZ extensions.
> >    - Support CPUCFG (CPU config) and CSR (Control and Status Register)
> >        extensions.
> >    - 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
> >        set-associative).
> >
> > Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
> > the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
> > 2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
> > which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
> > (e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
> > general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
> >
> > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > ---
> >   arch/mips/Kconfig                                  |  2 +
> >   arch/mips/include/asm/cpu.h                        |  4 +-
> >   .../asm/mach-loongson64/kernel-entry-init.h        | 28 +++++--
> >   arch/mips/kernel/cpu-probe.c                       | 15 +++-
> >   arch/mips/kernel/idle.c                            |  3 +-
> >   arch/mips/loongson64/loongson-3/smp.c              | 90 ++++++++++++----------
> >   arch/mips/mm/c-r4k.c                               |  3 +-
> >   drivers/platform/mips/cpu_hwmon.c                  | 14 +++-
> >   8 files changed, 107 insertions(+), 52 deletions(-)
> >
> > diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> > index 31c7044..3afcbce 100644
> > --- a/arch/mips/Kconfig
> > +++ b/arch/mips/Kconfig
> > @@ -1378,9 +1378,11 @@ config CPU_LOONGSON3
> >       select CPU_SUPPORTS_64BIT_KERNEL
> >       select CPU_SUPPORTS_HIGHMEM
> >       select CPU_SUPPORTS_HUGEPAGES
> > +     select CPU_SUPPORTS_MSA
> >       select CPU_HAS_LOAD_STORE_LR
> >       select WEAK_ORDERING
> >       select WEAK_REORDERING_BEYOND_LLSC
> > +     select MIPS_ASID_BITS_VARIABLE
> >       select MIPS_PGD_C0_CONTEXT
> >       select MIPS_L1_CACHE_SHIFT_6
> >       select GPIOLIB
> > diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
> > index 7fddcb8..81ddb57 100644
> > --- a/arch/mips/include/asm/cpu.h
> > +++ b/arch/mips/include/asm/cpu.h
> > @@ -91,7 +91,9 @@
> >   #define PRID_IMP_LOONGSON_32        0x4200  /* Loongson-1 */
> >   #define PRID_IMP_R5432              0x5400
> >   #define PRID_IMP_R5500              0x5500
> > -#define PRID_IMP_LOONGSON_64 0x6300  /* Loongson-2/3 */
> > +#define PRID_IMP_LOONGSON_64R        0x6100  /* Reduced Loongson-2 */
> > +#define PRID_IMP_LOONGSON_64C        0x6300  /* Classic Loongson-2 and Loongson-3 */
> > +#define PRID_IMP_LOONGSON_64G        0xc000  /* Generic Loongson-2 and Loongson-3 */
> >
> >   #define PRID_IMP_UNKNOWN    0xff00
> >
> > diff --git a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
> > index b5e288a..b968732 100644
> > --- a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
> > +++ b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
> > @@ -30,13 +30,21 @@
> >       mtc0    t0, CP0_PAGEGRAIN
> >       /* Enable STFill Buffer */
> >       mfc0    t0, CP0_PRID
> > +     /* Loongson-3A R4+ */
>
> Hi Huacai,
>
> For 3A R4+, Firmware will take care of SFB switch according tu Ruiyang
> Wu, the chief architect's words, are we still going to do that?
Hi, Jiaxun,

Enable SFB again is harmless, but more compatible.

>
> > +     andi    t1, t0, PRID_IMP_MASK
> > +     li      t2, PRID_IMP_LOONGSON_64G
> > +     beq     t1, t2, 1f
> > +     nop
> > +     /* Loongson-3A R2/R3 */
> >       andi    t0, (PRID_IMP_MASK | PRID_REV_MASK)
> > -     slti    t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2_0)
> > -     bnez    t0, 1f
> > +     slti    t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0)
> > +     bnez    t0, 2f
> > +     nop
> > +1:
> >       mfc0    t0, CP0_CONFIG6
> >       or      t0, 0x100
> >       mtc0    t0, CP0_CONFIG6
> > -1:
> > +2:
> >       _ehb
> >       .set    pop
> >   #endif
> > @@ -59,13 +67,21 @@
> >       mtc0    t0, CP0_PAGEGRAIN
> >       /* Enable STFill Buffer */
> >       mfc0    t0, CP0_PRID
> > +     /* Loongson-3A R4+ */
> > +     andi    t1, t0, PRID_IMP_MASK
> > +     li      t2, PRID_IMP_LOONGSON_64G
> > +     beq     t1, t2, 1f
> > +     nop
> The same.
> > +     /* Loongson-3A R2/R3 */
> >       andi    t0, (PRID_IMP_MASK | PRID_REV_MASK)
> > -     slti    t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2_0)
> > -     bnez    t0, 1f
> > +     slti    t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0)
> > +     bnez    t0, 2f
> > +     nop
> > +1:
> >       mfc0    t0, CP0_CONFIG6
> >       or      t0, 0x100
> >       mtc0    t0, CP0_CONFIG6
> > -1:
> > +2:
> >       _ehb
> >       .set    pop
> >   #endif
> > diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> > index c2eb392..09b2c67 100644
> > --- a/arch/mips/kernel/cpu-probe.c
> > +++ b/arch/mips/kernel/cpu-probe.c
> > @@ -1526,7 +1526,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
> >                            MIPS_CPU_LLSC | MIPS_CPU_BP_GHIST;
> >               c->tlbsize = 64;
> >               break;
> > -     case PRID_IMP_LOONGSON_64:  /* Loongson-2/3 */
> > +     case PRID_IMP_LOONGSON_64C:  /* Loongson-2/3 */
> >               switch (c->processor_id & PRID_REV_MASK) {
> >               case PRID_REV_LOONGSON2E:
> >                       c->cputype = CPU_LOONGSON2;
> > @@ -1903,7 +1903,7 @@ static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
> >   static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
> >   {
> >       switch (c->processor_id & PRID_IMP_MASK) {
> > -     case PRID_IMP_LOONGSON_64:  /* Loongson-2/3 */
> > +     case PRID_IMP_LOONGSON_64C:  /* Loongson-2/3 */
> >               switch (c->processor_id & PRID_REV_MASK) {
> >               case PRID_REV_LOONGSON3A_R2_0:
> >               case PRID_REV_LOONGSON3A_R2_1:
> > @@ -1927,6 +1927,17 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
> >               c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
> >                       MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
> >               break;
> > +     case PRID_IMP_LOONGSON_64G:
> > +             c->cputype = CPU_LOONGSON3;
> > +             __cpu_name[cpu] = "ICT Loongson-3";
> > +             set_elf_platform(cpu, "loongson3a");
> > +             set_isa(c, MIPS_CPU_ISA_M64R2);
> > +             decode_configs(c);
> > +             c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE;
> CPUCFG Register have bits to mark these features (ASEs, UCA). As we
> would never know what features would next Loongson product have, we'd
> better probe features by CPUCFG rather than PRID.

CPUCFG is not as reliable as PRID at present. And CPUCFG is not very
MIPS-native, I don't
want to use it in the basic support patch.

> > +             c->writecombine = _CACHE_UNCACHED_ACCELERATED;
> > +             c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
> > +                     MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
> > +             break;
> >       default:
> >               panic("Unknown Loongson Processor ID!");
> >               break;
> > diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
> > index eb2afc0..980d6c3 100644
> > --- a/arch/mips/kernel/idle.c
> > +++ b/arch/mips/kernel/idle.c
> > @@ -179,7 +179,8 @@ void __init check_wait(void)
> >               cpu_wait = r4k_wait;
> >               break;
> >       case CPU_LOONGSON3:
> > -             if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2_0)
> > +             if ((c->processor_id & (PRID_IMP_MASK | PRID_REV_MASK)) >=
> > +                             (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0))
> >                       cpu_wait = r4k_wait;
> The same. Probably we can have a Loongson feature flag in kernel to help
> with determining these features as PRID would never be a reliable way.
> As Yunqiang said, "I blame these Loongson guys here. Some Loongson guys
> is not so normal people. Anyway they are a little more normal now, and
> anyway again, still abnormal." You can never predict what will they do
> next. But the thing we can do is just reduce the cost of covering their
> next abnormal action in kernel.
> >               break;
> >
> > diff --git a/arch/mips/loongson64/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c
> > index ce68cda..e999bb1 100644
> > --- a/arch/mips/loongson64/loongson-3/smp.c
> > +++ b/arch/mips/loongson64/loongson-3/smp.c
> > @@ -450,7 +450,7 @@ static void loongson3_cpu_die(unsigned int cpu)
> >    * 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) */
> > -static void loongson3a_r1_play_dead(int *state_addr)
> > +static void loongson3_type1_play_dead(int *state_addr)
> >   {
> >       register int val;
> >       register long cpuid, core, node, count;
> > @@ -512,7 +512,7 @@ static void loongson3a_r1_play_dead(int *state_addr)
> >               : "a1");
> >   }
> >
> > -static void loongson3a_r2r3_play_dead(int *state_addr)
> > +static void loongson3_type2_play_dead(int *state_addr)
> >   {
> >       register int val;
> >       register long cpuid, core, node, count;
> > @@ -532,27 +532,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
> >               "   cache 1, 3(%[addr])           \n"
> >               "   addiu %[sets], %[sets], -1    \n"
> >               "   bnez  %[sets], 1b             \n"
> > -             "   addiu %[addr], %[addr], 0x40  \n"
> > -             "   li %[addr], 0x80000000        \n" /* KSEG0 */
> > -             "2: cache 2, 0(%[addr])           \n" /* flush L1 VCache */
> > -             "   cache 2, 1(%[addr])           \n"
> > -             "   cache 2, 2(%[addr])           \n"
> > -             "   cache 2, 3(%[addr])           \n"
> > -             "   cache 2, 4(%[addr])           \n"
> > -             "   cache 2, 5(%[addr])           \n"
> > -             "   cache 2, 6(%[addr])           \n"
> > -             "   cache 2, 7(%[addr])           \n"
> > -             "   cache 2, 8(%[addr])           \n"
> > -             "   cache 2, 9(%[addr])           \n"
> > -             "   cache 2, 10(%[addr])          \n"
> > -             "   cache 2, 11(%[addr])          \n"
> > -             "   cache 2, 12(%[addr])          \n"
> > -             "   cache 2, 13(%[addr])          \n"
> > -             "   cache 2, 14(%[addr])          \n"
> > -             "   cache 2, 15(%[addr])          \n"
> > -             "   addiu %[vsets], %[vsets], -1  \n"
> > -             "   bnez  %[vsets], 2b            \n"
> > -             "   addiu %[addr], %[addr], 0x40  \n"
> > +             "   addiu %[addr], %[addr], 0x20  \n"
> >               "   li    %[val], 0x7             \n" /* *state_addr = CPU_DEAD; */
> >               "   sw    %[val], (%[state_addr]) \n"
> >               "   sync                          \n"
> > @@ -560,8 +540,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
> >               "   .set pop                      \n"
> >               : [addr] "=&r" (addr), [val] "=&r" (val)
> >               : [state_addr] "r" (state_addr),
> > -               [sets] "r" (cpu_data[smp_processor_id()].dcache.sets),
> > -               [vsets] "r" (cpu_data[smp_processor_id()].vcache.sets));
> > +               [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
> >
> >       __asm__ __volatile__(
> >               "   .set push                         \n"
> > @@ -576,6 +555,8 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
> >               "   andi  %[node], %[cpuid], 0xc      \n"
> >               "   dsll  %[node], 42                 \n" /* get node id */
> >               "   or    %[base], %[base], %[node]   \n"
> > +             "   dsrl  %[node], 30                 \n" /* 15:14 */
> > +             "   or    %[base], %[base], %[node]   \n"
> >               "1: li    %[count], 0x100             \n" /* wait for init loop */
> >               "2: bnez  %[count], 2b                \n" /* limit mailbox access */
> >               "   addiu %[count], -1                \n"
> > @@ -595,7 +576,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
> >               : "a1");
> >   }
> >
> > -static void loongson3b_play_dead(int *state_addr)
> > +static void loongson3_type3_play_dead(int *state_addr)
> >   {
> >       register int val;
> >       register long cpuid, core, node, count;
> > @@ -615,7 +596,27 @@ static void loongson3b_play_dead(int *state_addr)
> >               "   cache 1, 3(%[addr])           \n"
> >               "   addiu %[sets], %[sets], -1    \n"
> >               "   bnez  %[sets], 1b             \n"
> > -             "   addiu %[addr], %[addr], 0x20  \n"
> > +             "   addiu %[addr], %[addr], 0x40  \n"
> > +             "   li %[addr], 0x80000000        \n" /* KSEG0 */
> > +             "2: cache 2, 0(%[addr])           \n" /* flush L1 VCache */
> > +             "   cache 2, 1(%[addr])           \n"
> > +             "   cache 2, 2(%[addr])           \n"
> > +             "   cache 2, 3(%[addr])           \n"
> > +             "   cache 2, 4(%[addr])           \n"
> > +             "   cache 2, 5(%[addr])           \n"
> > +             "   cache 2, 6(%[addr])           \n"
> > +             "   cache 2, 7(%[addr])           \n"
> > +             "   cache 2, 8(%[addr])           \n"
> > +             "   cache 2, 9(%[addr])           \n"
> > +             "   cache 2, 10(%[addr])          \n"
> > +             "   cache 2, 11(%[addr])          \n"
> > +             "   cache 2, 12(%[addr])          \n"
> > +             "   cache 2, 13(%[addr])          \n"
> > +             "   cache 2, 14(%[addr])          \n"
> > +             "   cache 2, 15(%[addr])          \n"
> > +             "   addiu %[vsets], %[vsets], -1  \n"
> > +             "   bnez  %[vsets], 2b            \n"
> > +             "   addiu %[addr], %[addr], 0x40  \n"
> >               "   li    %[val], 0x7             \n" /* *state_addr = CPU_DEAD; */
> >               "   sw    %[val], (%[state_addr]) \n"
> >               "   sync                          \n"
> > @@ -623,7 +624,8 @@ static void loongson3b_play_dead(int *state_addr)
> >               "   .set pop                      \n"
> >               : [addr] "=&r" (addr), [val] "=&r" (val)
> >               : [state_addr] "r" (state_addr),
> > -               [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
> > +               [sets] "r" (cpu_data[smp_processor_id()].dcache.sets),
> > +               [vsets] "r" (cpu_data[smp_processor_id()].vcache.sets));
> >
> >       __asm__ __volatile__(
> >               "   .set push                         \n"
> > @@ -638,8 +640,6 @@ static void loongson3b_play_dead(int *state_addr)
> >               "   andi  %[node], %[cpuid], 0xc      \n"
> >               "   dsll  %[node], 42                 \n" /* get node id */
> >               "   or    %[base], %[base], %[node]   \n"
> > -             "   dsrl  %[node], 30                 \n" /* 15:14 */
> > -             "   or    %[base], %[base], %[node]   \n"
> >               "1: li    %[count], 0x100             \n" /* wait for init loop */
> >               "2: bnez  %[count], 2b                \n" /* limit mailbox access */
> >               "   addiu %[count], -1                \n"
> > @@ -661,30 +661,42 @@ static void loongson3b_play_dead(int *state_addr)
> >
> >   void play_dead(void)
> >   {
> > -     int *state_addr;
> > +     int prid_imp, prid_rev, *state_addr;
> >       unsigned int cpu = smp_processor_id();
> >       void (*play_dead_at_ckseg1)(int *);
> >
> >       idle_task_exit();
> > -     switch (read_c0_prid() & PRID_REV_MASK) {
> > +
> > +     prid_imp = read_c0_prid() & PRID_IMP_MASK;
> > +     prid_rev = read_c0_prid() & PRID_REV_MASK;
> > +
> > +     if (prid_imp == PRID_IMP_LOONGSON_64G) {
> > +             play_dead_at_ckseg1 =
> > +                     (void *)CKSEG1ADDR((unsigned long)loongson3_type3_play_dead);
> > +             goto out;
> > +     }
> > +
> > +     switch (prid_rev) {
> >       case PRID_REV_LOONGSON3A_R1:
> >       default:
> >               play_dead_at_ckseg1 =
> > -                     (void *)CKSEG1ADDR((unsigned long)loongson3a_r1_play_dead);
> > +                     (void *)CKSEG1ADDR((unsigned long)loongson3_type1_play_dead);
> > +             break;
> > +     case PRID_REV_LOONGSON3B_R1:
> > +     case PRID_REV_LOONGSON3B_R2:
> > +             play_dead_at_ckseg1 =
> > +                     (void *)CKSEG1ADDR((unsigned long)loongson3_type2_play_dead);
> >               break;
> >       case PRID_REV_LOONGSON3A_R2_0:
> >       case PRID_REV_LOONGSON3A_R2_1:
> >       case PRID_REV_LOONGSON3A_R3_0:
> >       case PRID_REV_LOONGSON3A_R3_1:
> >               play_dead_at_ckseg1 =
> > -                     (void *)CKSEG1ADDR((unsigned long)loongson3a_r2r3_play_dead);
> > -             break;
> > -     case PRID_REV_LOONGSON3B_R1:
> > -     case PRID_REV_LOONGSON3B_R2:
> > -             play_dead_at_ckseg1 =
> > -                     (void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
> > +                     (void *)CKSEG1ADDR((unsigned long)loongson3_type3_play_dead);
> >               break;
> >       }
> > +
> > +out:
> >       state_addr = &per_cpu(cpu_state, cpu);
> >       mb();
> >       play_dead_at_ckseg1(state_addr);
>
> Things we're doing in playdead are mostly duplicated. Flushing cache,
> broadcasting CPU state, then doing loops to wait a mailbox PC. Probably
> we can reuse r4k cache ops here to avoid too much assembly. And reuse
> Mailbox loop code as they're almost the same.
I have tried r4k cache ops but I've failed, those macros are not very suitable
in this uncache situation.

Huacai

>
> --
>
> Jiaxun Yang
>
> > diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
> > index 89b9c85..4bf9906 100644
> > --- a/arch/mips/mm/c-r4k.c
> > +++ b/arch/mips/mm/c-r4k.c
> > @@ -1267,7 +1267,8 @@ static void probe_pcache(void)
> >                                         c->dcache.ways *
> >                                         c->dcache.linesz;
> >               c->dcache.waybit = 0;
> > -             if ((prid & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2_0)
> > +             if ((c->processor_id & (PRID_IMP_MASK | PRID_REV_MASK)) >=
> > +                             (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0))
> >                       c->options |= MIPS_CPU_PREFETCH;
> >               break;
> >
> > diff --git a/drivers/platform/mips/cpu_hwmon.c b/drivers/platform/mips/cpu_hwmon.c
> > index a7f184b..15ca8bf 100644
> > --- a/drivers/platform/mips/cpu_hwmon.c
> > +++ b/drivers/platform/mips/cpu_hwmon.c
> > @@ -9,6 +9,7 @@
> >   #include <loongson.h>
> >   #include <boot_param.h>
> >   #include <loongson_hwmon.h>
> > +#include <loongson_regs.h>
> >
> >   /*
> >    * Loongson-3 series cpu has two sensors inside,
> > @@ -18,10 +19,17 @@
> >    */
> >   int loongson3_cpu_temp(int cpu)
> >   {
> > -     u32 reg, prid_rev;
> > +     u32 reg, prid_imp, prid_rev;
> >
> > -     reg = LOONGSON_CHIPTEMP(cpu);
> > +     prid_imp = read_c0_prid() & PRID_IMP_MASK;
> >       prid_rev = read_c0_prid() & PRID_REV_MASK;
> > +
> > +     if(prid_imp == PRID_IMP_LOONGSON_64G) {
> > +             reg = (csr_readl(LOONGSON_CSR_CPUTEMP) & 0xff);
> > +             goto out;
> > +     }
> > +
> > +     reg = LOONGSON_CHIPTEMP(cpu);
> >       switch (prid_rev) {
> >       case PRID_REV_LOONGSON3A_R1:
> >               reg = (reg >> 8) & 0xff;
> > @@ -37,6 +45,8 @@ int loongson3_cpu_temp(int cpu)
> >               reg = (reg & 0xffff)*731/0x4000 - 273;
> >               break;
> >       }
> > +
> > +out:
> >       return (int)reg * 1000;
> >   }
> >

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

* Re: [PATCH 2/3] MIPS: Loongson: Add Loongson-3A R4 basic support
  2019-09-04  3:43     ` Huacai Chen
@ 2019-09-04  6:03       ` Jiaxun Yang
  0 siblings, 0 replies; 5+ messages in thread
From: Jiaxun Yang @ 2019-09-04  6:03 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Paul Burton, Ralf Baechle, James Hogan, Linux MIPS Mailing List,
	open list:MIPS, Fuxin Zhang, Zhangjin Wu


在 2019/9/4 11:43, Huacai Chen 写道:
> On Tue, Sep 3, 2019 at 2:40 PM Jiaxun Yang <jiaxun.yang@flygoat.com> wrote:
>>
>> 在 2019/9/1 15:49, Huacai Chen 写道:
>>> All Loongson-3 CPU family:
>>>
>>> Code-name         Brand-name       PRId
>>> Loongson-3A R1    Loongson-3A1000  0x6305
>>> Loongson-3A R2    Loongson-3A2000  0x6308
>>> Loongson-3A R2.1  Loongson-3A2000  0x630c
>>> Loongson-3A R3    Loongson-3A3000  0x6309
>>> Loongson-3A R3.1  Loongson-3A3000  0x630d
>>> Loongson-3A R4    Loongson-3A4000  0xc000
>>> Loongson-3B R1    Loongson-3B1000  0x6306
>>> Loongson-3B R2    Loongson-3B1500  0x6307
>>>
>>> Features of R4 revision of Loongson-3A:
>>>
>>>     - All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
>>>     - Support variable ASID bits.
>>>     - Support MSA and VZ extensions.
>>>     - Support CPUCFG (CPU config) and CSR (Control and Status Register)
>>>         extensions.
>>>     - 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
>>>         set-associative).
>>>
>>> Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
>>> the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
>>> 2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
>>> which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
>>> (e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
>>> general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
>>>
>>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
>>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>> ---
>>>    arch/mips/Kconfig                                  |  2 +
>>>    arch/mips/include/asm/cpu.h                        |  4 +-
>>>    .../asm/mach-loongson64/kernel-entry-init.h        | 28 +++++--
>>>    arch/mips/kernel/cpu-probe.c                       | 15 +++-
>>>    arch/mips/kernel/idle.c                            |  3 +-
>>>    arch/mips/loongson64/loongson-3/smp.c              | 90 ++++++++++++----------
>>>    arch/mips/mm/c-r4k.c                               |  3 +-
>>>    drivers/platform/mips/cpu_hwmon.c                  | 14 +++-
>>>    8 files changed, 107 insertions(+), 52 deletions(-)
>>>
>>> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
>>> index 31c7044..3afcbce 100644
>>> --- a/arch/mips/Kconfig
>>> +++ b/arch/mips/Kconfig
>>> @@ -1378,9 +1378,11 @@ config CPU_LOONGSON3
>>>        select CPU_SUPPORTS_64BIT_KERNEL
>>>        select CPU_SUPPORTS_HIGHMEM
>>>        select CPU_SUPPORTS_HUGEPAGES
>>> +     select CPU_SUPPORTS_MSA
>>>        select CPU_HAS_LOAD_STORE_LR
>>>        select WEAK_ORDERING
>>>        select WEAK_REORDERING_BEYOND_LLSC
>>> +     select MIPS_ASID_BITS_VARIABLE
>>>        select MIPS_PGD_C0_CONTEXT
>>>        select MIPS_L1_CACHE_SHIFT_6
>>>        select GPIOLIB
>>> diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
>>> index 7fddcb8..81ddb57 100644
>>> --- a/arch/mips/include/asm/cpu.h
>>> +++ b/arch/mips/include/asm/cpu.h
>>> @@ -91,7 +91,9 @@
>>>    #define PRID_IMP_LOONGSON_32        0x4200  /* Loongson-1 */
>>>    #define PRID_IMP_R5432              0x5400
>>>    #define PRID_IMP_R5500              0x5500
>>> -#define PRID_IMP_LOONGSON_64 0x6300  /* Loongson-2/3 */
>>> +#define PRID_IMP_LOONGSON_64R        0x6100  /* Reduced Loongson-2 */
>>> +#define PRID_IMP_LOONGSON_64C        0x6300  /* Classic Loongson-2 and Loongson-3 */
>>> +#define PRID_IMP_LOONGSON_64G        0xc000  /* Generic Loongson-2 and Loongson-3 */
>>>
>>>    #define PRID_IMP_UNKNOWN    0xff00
>>>
>>> diff --git a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
>>> index b5e288a..b968732 100644
>>> --- a/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
>>> +++ b/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
>>> @@ -30,13 +30,21 @@
>>>        mtc0    t0, CP0_PAGEGRAIN
>>>        /* Enable STFill Buffer */
>>>        mfc0    t0, CP0_PRID
>>> +     /* Loongson-3A R4+ */
>> Hi Huacai,
>>
>> For 3A R4+, Firmware will take care of SFB switch according tu Ruiyang
>> Wu, the chief architect's words, are we still going to do that?
> Hi, Jiaxun,
>
> Enable SFB again is harmless, but more compatible.
>
> CPUCFG is not as reliable as PRID at present. And CPUCFG is not very
> MIPS-native, I don't
> want to use it in the basic support patch.

Wish we won't stop at "Basic Support" in mainline.

You're right : - )

Or we can deliver CPUCFG related probe code under loongson64?

>
>>> +             c->writecombine = _CACHE_UNCACHED_ACCELERATED;
>>> +             c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
>>> +                     MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
>>> +             break;
>>>        default:
>>>                panic("Unknown Loongson Processor ID!");
>>>                break;
>>> diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
>>> index eb2afc0..980d6c3 100644
>>> --- a/arch/mips/kernel/idle.c
>>> +++ b/arch/mips/kernel/idle.c
>>> @@ -179,7 +179,8 @@ void __init check_wait(void)
>>>                cpu_wait = r4k_wait;
>>>                break;
>>>        case CPU_LOONGSON3:
>>> -             if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2_0)
>>> +             if ((c->processor_id & (PRID_IMP_MASK | PRID_REV_MASK)) >=
>>> +                             (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0))
>>>                        cpu_wait = r4k_wait;
>> The same. Probably we can have a Loongson feature flag in kernel to help
>> with determining these features as PRID would never be a reliable way.
>> As Yunqiang said, "I blame these Loongson guys here. Some Loongson guys
>> is not so normal people. Anyway they are a little more normal now, and
>> anyway again, still abnormal." You can never predict what will they do
>> next. But the thing we can do is just reduce the cost of covering their
>> next abnormal action in kernel.
>>>                break;
>>>
>>> diff --git a/arch/mips/loongson64/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c
>>> index ce68cda..e999bb1 100644
>>> --- a/arch/mips/loongson64/loongson-3/smp.c
>>> +++ b/arch/mips/loongson64/loongson-3/smp.c
>>> @@ -450,7 +450,7 @@ static void loongson3_cpu_die(unsigned int cpu)
>>>     * 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) */
>>> -static void loongson3a_r1_play_dead(int *state_addr)
>>> +static void loongson3_type1_play_dead(int *state_addr)
>>>    {
>>>        register int val;
>>>        register long cpuid, core, node, count;
>>> @@ -512,7 +512,7 @@ static void loongson3a_r1_play_dead(int *state_addr)
>>>                : "a1");
>>>    }
>>>
>>> -static void loongson3a_r2r3_play_dead(int *state_addr)
>>> +static void loongson3_type2_play_dead(int *state_addr)
>>>    {
>>>        register int val;
>>>        register long cpuid, core, node, count;
>>> @@ -532,27 +532,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
>>>                "   cache 1, 3(%[addr])           \n"
>>>                "   addiu %[sets], %[sets], -1    \n"
>>>                "   bnez  %[sets], 1b             \n"
>>> -             "   addiu %[addr], %[addr], 0x40  \n"
>>> -             "   li %[addr], 0x80000000        \n" /* KSEG0 */
>>> -             "2: cache 2, 0(%[addr])           \n" /* flush L1 VCache */
>>> -             "   cache 2, 1(%[addr])           \n"
>>> -             "   cache 2, 2(%[addr])           \n"
>>> -             "   cache 2, 3(%[addr])           \n"
>>> -             "   cache 2, 4(%[addr])           \n"
>>> -             "   cache 2, 5(%[addr])           \n"
>>> -             "   cache 2, 6(%[addr])           \n"
>>> -             "   cache 2, 7(%[addr])           \n"
>>> -             "   cache 2, 8(%[addr])           \n"
>>> -             "   cache 2, 9(%[addr])           \n"
>>> -             "   cache 2, 10(%[addr])          \n"
>>> -             "   cache 2, 11(%[addr])          \n"
>>> -             "   cache 2, 12(%[addr])          \n"
>>> -             "   cache 2, 13(%[addr])          \n"
>>> -             "   cache 2, 14(%[addr])          \n"
>>> -             "   cache 2, 15(%[addr])          \n"
>>> -             "   addiu %[vsets], %[vsets], -1  \n"
>>> -             "   bnez  %[vsets], 2b            \n"
>>> -             "   addiu %[addr], %[addr], 0x40  \n"
>>> +             "   addiu %[addr], %[addr], 0x20  \n"
>>>                "   li    %[val], 0x7             \n" /* *state_addr = CPU_DEAD; */
>>>                "   sw    %[val], (%[state_addr]) \n"
>>>                "   sync                          \n"
>>> @@ -560,8 +540,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
>>>                "   .set pop                      \n"
>>>                : [addr] "=&r" (addr), [val] "=&r" (val)
>>>                : [state_addr] "r" (state_addr),
>>> -               [sets] "r" (cpu_data[smp_processor_id()].dcache.sets),
>>> -               [vsets] "r" (cpu_data[smp_processor_id()].vcache.sets));
>>> +               [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
>>>
>>>        __asm__ __volatile__(
>>>                "   .set push                         \n"
>>> @@ -576,6 +555,8 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
>>>                "   andi  %[node], %[cpuid], 0xc      \n"
>>>                "   dsll  %[node], 42                 \n" /* get node id */
>>>                "   or    %[base], %[base], %[node]   \n"
>>> +             "   dsrl  %[node], 30                 \n" /* 15:14 */
>>> +             "   or    %[base], %[base], %[node]   \n"
>>>                "1: li    %[count], 0x100             \n" /* wait for init loop */
>>>                "2: bnez  %[count], 2b                \n" /* limit mailbox access */
>>>                "   addiu %[count], -1                \n"
>>> @@ -595,7 +576,7 @@ static void loongson3a_r2r3_play_dead(int *state_addr)
>>>                : "a1");
>>>    }
>>>
>>> -static void loongson3b_play_dead(int *state_addr)
>>> +static void loongson3_type3_play_dead(int *state_addr)
>>>    {
>>>        register int val;
>>>        register long cpuid, core, node, count;
>>> @@ -615,7 +596,27 @@ static void loongson3b_play_dead(int *state_addr)
>>>                "   cache 1, 3(%[addr])           \n"
>>>                "   addiu %[sets], %[sets], -1    \n"
>>>                "   bnez  %[sets], 1b             \n"
>>> -             "   addiu %[addr], %[addr], 0x20  \n"
>>> +             "   addiu %[addr], %[addr], 0x40  \n"
>>> +             "   li %[addr], 0x80000000        \n" /* KSEG0 */
>>> +             "2: cache 2, 0(%[addr])           \n" /* flush L1 VCache */
>>> +             "   cache 2, 1(%[addr])           \n"
>>> +             "   cache 2, 2(%[addr])           \n"
>>> +             "   cache 2, 3(%[addr])           \n"
>>> +             "   cache 2, 4(%[addr])           \n"
>>> +             "   cache 2, 5(%[addr])           \n"
>>> +             "   cache 2, 6(%[addr])           \n"
>>> +             "   cache 2, 7(%[addr])           \n"
>>> +             "   cache 2, 8(%[addr])           \n"
>>> +             "   cache 2, 9(%[addr])           \n"
>>> +             "   cache 2, 10(%[addr])          \n"
>>> +             "   cache 2, 11(%[addr])          \n"
>>> +             "   cache 2, 12(%[addr])          \n"
>>> +             "   cache 2, 13(%[addr])          \n"
>>> +             "   cache 2, 14(%[addr])          \n"
>>> +             "   cache 2, 15(%[addr])          \n"
>>> +             "   addiu %[vsets], %[vsets], -1  \n"
>>> +             "   bnez  %[vsets], 2b            \n"
>>> +             "   addiu %[addr], %[addr], 0x40  \n"
>>>                "   li    %[val], 0x7             \n" /* *state_addr = CPU_DEAD; */
>>>                "   sw    %[val], (%[state_addr]) \n"
>>>                "   sync                          \n"
>>> @@ -623,7 +624,8 @@ static void loongson3b_play_dead(int *state_addr)
>>>                "   .set pop                      \n"
>>>                : [addr] "=&r" (addr), [val] "=&r" (val)
>>>                : [state_addr] "r" (state_addr),
>>> -               [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
>>> +               [sets] "r" (cpu_data[smp_processor_id()].dcache.sets),
>>> +               [vsets] "r" (cpu_data[smp_processor_id()].vcache.sets));
>>>
>>>        __asm__ __volatile__(
>>>                "   .set push                         \n"
>>> @@ -638,8 +640,6 @@ static void loongson3b_play_dead(int *state_addr)
>>>                "   andi  %[node], %[cpuid], 0xc      \n"
>>>                "   dsll  %[node], 42                 \n" /* get node id */
>>>                "   or    %[base], %[base], %[node]   \n"
>>> -             "   dsrl  %[node], 30                 \n" /* 15:14 */
>>> -             "   or    %[base], %[base], %[node]   \n"
>>>                "1: li    %[count], 0x100             \n" /* wait for init loop */
>>>                "2: bnez  %[count], 2b                \n" /* limit mailbox access */
>>>                "   addiu %[count], -1                \n"
>>> @@ -661,30 +661,42 @@ static void loongson3b_play_dead(int *state_addr)
>>>
>>>    void play_dead(void)
>>>    {
>>> -     int *state_addr;
>>> +     int prid_imp, prid_rev, *state_addr;
>>>        unsigned int cpu = smp_processor_id();
>>>        void (*play_dead_at_ckseg1)(int *);
>>>
>>>        idle_task_exit();
>>> -     switch (read_c0_prid() & PRID_REV_MASK) {
>>> +
>>> +     prid_imp = read_c0_prid() & PRID_IMP_MASK;
>>> +     prid_rev = read_c0_prid() & PRID_REV_MASK;
>>> +
>>> +     if (prid_imp == PRID_IMP_LOONGSON_64G) {
>>> +             play_dead_at_ckseg1 =
>>> +                     (void *)CKSEG1ADDR((unsigned long)loongson3_type3_play_dead);
>>> +             goto out;
>>> +     }
>>> +
>>> +     switch (prid_rev) {
>>>        case PRID_REV_LOONGSON3A_R1:
>>>        default:
>>>                play_dead_at_ckseg1 =
>>> -                     (void *)CKSEG1ADDR((unsigned long)loongson3a_r1_play_dead);
>>> +                     (void *)CKSEG1ADDR((unsigned long)loongson3_type1_play_dead);
>>> +             break;
>>> +     case PRID_REV_LOONGSON3B_R1:
>>> +     case PRID_REV_LOONGSON3B_R2:
>>> +             play_dead_at_ckseg1 =
>>> +                     (void *)CKSEG1ADDR((unsigned long)loongson3_type2_play_dead);
>>>                break;
>>>        case PRID_REV_LOONGSON3A_R2_0:
>>>        case PRID_REV_LOONGSON3A_R2_1:
>>>        case PRID_REV_LOONGSON3A_R3_0:
>>>        case PRID_REV_LOONGSON3A_R3_1:
>>>                play_dead_at_ckseg1 =
>>> -                     (void *)CKSEG1ADDR((unsigned long)loongson3a_r2r3_play_dead);
>>> -             break;
>>> -     case PRID_REV_LOONGSON3B_R1:
>>> -     case PRID_REV_LOONGSON3B_R2:
>>> -             play_dead_at_ckseg1 =
>>> -                     (void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
>>> +                     (void *)CKSEG1ADDR((unsigned long)loongson3_type3_play_dead);
>>>                break;
>>>        }
>>> +
>>> +out:
>>>        state_addr = &per_cpu(cpu_state, cpu);
>>>        mb();
>>>        play_dead_at_ckseg1(state_addr);
>> Things we're doing in playdead are mostly duplicated. Flushing cache,
>> broadcasting CPU state, then doing loops to wait a mailbox PC. Probably
>> we can reuse r4k cache ops here to avoid too much assembly. And reuse
>> Mailbox loop code as they're almost the same.
> I have tried r4k cache ops but I've failed, those macros are not very suitable
> in this uncache situation.
run_uncached? At least we can reuse flush assembly code.
>
> Huacai
>
>> --
>>
>> Jiaxun Yang
>>
>>> diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
>>> index 89b9c85..4bf9906 100644
>>> --- a/arch/mips/mm/c-r4k.c
>>> +++ b/arch/mips/mm/c-r4k.c
>>> @@ -1267,7 +1267,8 @@ static void probe_pcache(void)
>>>                                          c->dcache.ways *
>>>                                          c->dcache.linesz;
>>>                c->dcache.waybit = 0;
>>> -             if ((prid & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2_0)
>>> +             if ((c->processor_id & (PRID_IMP_MASK | PRID_REV_MASK)) >=
>>> +                             (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0))
>>>                        c->options |= MIPS_CPU_PREFETCH;
>>>                break;
>>>
>>> diff --git a/drivers/platform/mips/cpu_hwmon.c b/drivers/platform/mips/cpu_hwmon.c
>>> index a7f184b..15ca8bf 100644
>>> --- a/drivers/platform/mips/cpu_hwmon.c
>>> +++ b/drivers/platform/mips/cpu_hwmon.c
>>> @@ -9,6 +9,7 @@
>>>    #include <loongson.h>
>>>    #include <boot_param.h>
>>>    #include <loongson_hwmon.h>
>>> +#include <loongson_regs.h>
>>>
>>>    /*
>>>     * Loongson-3 series cpu has two sensors inside,
>>> @@ -18,10 +19,17 @@
>>>     */
>>>    int loongson3_cpu_temp(int cpu)
>>>    {
>>> -     u32 reg, prid_rev;
>>> +     u32 reg, prid_imp, prid_rev;
>>>
>>> -     reg = LOONGSON_CHIPTEMP(cpu);
>>> +     prid_imp = read_c0_prid() & PRID_IMP_MASK;
>>>        prid_rev = read_c0_prid() & PRID_REV_MASK;
>>> +
>>> +     if(prid_imp == PRID_IMP_LOONGSON_64G) {
>>> +             reg = (csr_readl(LOONGSON_CSR_CPUTEMP) & 0xff);
>>> +             goto out;
>>> +     }
>>> +
>>> +     reg = LOONGSON_CHIPTEMP(cpu);
>>>        switch (prid_rev) {
>>>        case PRID_REV_LOONGSON3A_R1:
>>>                reg = (reg >> 8) & 0xff;
>>> @@ -37,6 +45,8 @@ int loongson3_cpu_temp(int cpu)
>>>                reg = (reg & 0xffff)*731/0x4000 - 273;
>>>                break;
>>>        }
>>> +
>>> +out:
>>>        return (int)reg * 1000;
>>>    }
>>>

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

end of thread, other threads:[~2019-09-04  6:04 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-01  7:49 [PATCH 1/3] MIPS: Loongson: Add CFUCFG&CSR support Huacai Chen
2019-09-01  7:49 ` [PATCH 2/3] MIPS: Loongson: Add Loongson-3A R4 basic support Huacai Chen
2019-09-03  6:39   ` Jiaxun Yang
2019-09-04  3:43     ` Huacai Chen
2019-09-04  6:03       ` Jiaxun Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).