All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/19] Initial I6400 and CM3 support
@ 2015-07-09  9:40 ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Hi,

This patchset adds support for I6400 processor along with the new
Coherent Manager 3.

More information about the I-Class Warrior family can be found below:

http://www.imgtec.com/mips/warrior/iclass.asp

Markos Chandras (15):
  MIPS: Add MIPS I6400 PRid and cputype identifiers
  MIPS: Add cases for CPU_I6400
  MIPS: Add MIPS I6400 probe support
  MIPS: Kconfig: Disable MIPS MT and SMP implementations for R6
  MIPS: Add platform callback before initializing the L2 cache
  MIPS: asm: mips-cm: Extend CM accessors for 64-bit CPUs
  MIPS: kernel: mips-cm: The CMGCRBase register is 64-bit on MIPS64
  MIPS: kernel: mips-cpc: Fix type for GCR CPC base reg for 64-bit
  MIPS: kernel: mips-cm: Add support for reporting CM cache errors
  drivers: irqchip: irq-mips-gic: Extend GIC accessors for 64-bit CMs
  drivers: irqchip: irq-mips-gic: Add support for CM3 64-bit timer irqs
  MIPS: kernel: cpu-probe: Remove cp0 hazard barrier when enabling the
    FTLB
  MIPS: Add default case for the FTLB enable/disable code
  MIPS: kernel: cpu-probe: Fix VTLB/FTLB configuration for R6
  MIPS: Set up FTLB probability for I6400

Paul Burton (4):
  MIPS: asm: mips-cm: Implement mips_cm_revision
  MIPS: asm: add CM GCR_L2_CONFIG register accessors
  MIPS: mm: c-r4k: extend way_string array
  MIPS: support CM3 L2 cache

 arch/mips/Kconfig                    |   6 +-
 arch/mips/include/asm/cpu-type.h     |   4 +
 arch/mips/include/asm/cpu.h          |   2 +
 arch/mips/include/asm/mips-cm.h      |  97 ++++++++++++-
 arch/mips/include/asm/mipsregs.h     |   2 +
 arch/mips/kernel/cpu-probe.c         |  47 +++++--
 arch/mips/kernel/idle.c              |   1 +
 arch/mips/kernel/mips-cm.c           | 257 ++++++++++++++++++++++++++++++++++-
 arch/mips/kernel/mips-cpc.c          |   2 +-
 arch/mips/kernel/perf_event_mipsxx.c |   6 +
 arch/mips/kernel/pm-cps.c            |   2 +
 arch/mips/kernel/spram.c             |   1 +
 arch/mips/kernel/traps.c             |   1 +
 arch/mips/mm/c-r4k.c                 |   5 +-
 arch/mips/mm/sc-mips.c               |  42 ++++++
 arch/mips/mti-malta/malta-init.c     |   7 +
 arch/mips/mti-malta/malta-int.c      | 112 +--------------
 arch/mips/oprofile/common.c          |   1 +
 arch/mips/oprofile/op_model_mipsxx.c |   4 +
 drivers/irqchip/irq-mips-gic.c       | 140 ++++++++++++-------
 include/linux/irqchip/mips-gic.h     |  14 +-
 21 files changed, 573 insertions(+), 180 deletions(-)

-- 
2.4.5

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

* [PATCH 00/19] Initial I6400 and CM3 support
@ 2015-07-09  9:40 ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Hi,

This patchset adds support for I6400 processor along with the new
Coherent Manager 3.

More information about the I-Class Warrior family can be found below:

http://www.imgtec.com/mips/warrior/iclass.asp

Markos Chandras (15):
  MIPS: Add MIPS I6400 PRid and cputype identifiers
  MIPS: Add cases for CPU_I6400
  MIPS: Add MIPS I6400 probe support
  MIPS: Kconfig: Disable MIPS MT and SMP implementations for R6
  MIPS: Add platform callback before initializing the L2 cache
  MIPS: asm: mips-cm: Extend CM accessors for 64-bit CPUs
  MIPS: kernel: mips-cm: The CMGCRBase register is 64-bit on MIPS64
  MIPS: kernel: mips-cpc: Fix type for GCR CPC base reg for 64-bit
  MIPS: kernel: mips-cm: Add support for reporting CM cache errors
  drivers: irqchip: irq-mips-gic: Extend GIC accessors for 64-bit CMs
  drivers: irqchip: irq-mips-gic: Add support for CM3 64-bit timer irqs
  MIPS: kernel: cpu-probe: Remove cp0 hazard barrier when enabling the
    FTLB
  MIPS: Add default case for the FTLB enable/disable code
  MIPS: kernel: cpu-probe: Fix VTLB/FTLB configuration for R6
  MIPS: Set up FTLB probability for I6400

Paul Burton (4):
  MIPS: asm: mips-cm: Implement mips_cm_revision
  MIPS: asm: add CM GCR_L2_CONFIG register accessors
  MIPS: mm: c-r4k: extend way_string array
  MIPS: support CM3 L2 cache

 arch/mips/Kconfig                    |   6 +-
 arch/mips/include/asm/cpu-type.h     |   4 +
 arch/mips/include/asm/cpu.h          |   2 +
 arch/mips/include/asm/mips-cm.h      |  97 ++++++++++++-
 arch/mips/include/asm/mipsregs.h     |   2 +
 arch/mips/kernel/cpu-probe.c         |  47 +++++--
 arch/mips/kernel/idle.c              |   1 +
 arch/mips/kernel/mips-cm.c           | 257 ++++++++++++++++++++++++++++++++++-
 arch/mips/kernel/mips-cpc.c          |   2 +-
 arch/mips/kernel/perf_event_mipsxx.c |   6 +
 arch/mips/kernel/pm-cps.c            |   2 +
 arch/mips/kernel/spram.c             |   1 +
 arch/mips/kernel/traps.c             |   1 +
 arch/mips/mm/c-r4k.c                 |   5 +-
 arch/mips/mm/sc-mips.c               |  42 ++++++
 arch/mips/mti-malta/malta-init.c     |   7 +
 arch/mips/mti-malta/malta-int.c      | 112 +--------------
 arch/mips/oprofile/common.c          |   1 +
 arch/mips/oprofile/op_model_mipsxx.c |   4 +
 drivers/irqchip/irq-mips-gic.c       | 140 ++++++++++++-------
 include/linux/irqchip/mips-gic.h     |  14 +-
 21 files changed, 573 insertions(+), 180 deletions(-)

-- 
2.4.5

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

* [PATCH 01/19] MIPS: Add MIPS I6400 PRid and cputype identifiers
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add a Processor ID and CPU type for the MIPS I6400 core.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/cpu.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index e46e40602af3..5fa7b8ba48a9 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -120,6 +120,7 @@
 #define PRID_IMP_PROAPTIV_MP	0xa300
 #define PRID_IMP_M5150		0xa700
 #define PRID_IMP_P5600		0xa800
+#define PRID_IMP_I6400		0xa900
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
@@ -307,6 +308,7 @@ enum cpu_type_enum {
 	CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
 	CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC,
 	CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K, CPU_M5150,
+	CPU_I6400,
 
 	/*
 	 * MIPS64 class processors
-- 
2.4.5

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

* [PATCH 01/19] MIPS: Add MIPS I6400 PRid and cputype identifiers
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add a Processor ID and CPU type for the MIPS I6400 core.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/cpu.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index e46e40602af3..5fa7b8ba48a9 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -120,6 +120,7 @@
 #define PRID_IMP_PROAPTIV_MP	0xa300
 #define PRID_IMP_M5150		0xa700
 #define PRID_IMP_P5600		0xa800
+#define PRID_IMP_I6400		0xa900
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
@@ -307,6 +308,7 @@ enum cpu_type_enum {
 	CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
 	CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC,
 	CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K, CPU_M5150,
+	CPU_I6400,
 
 	/*
 	 * MIPS64 class processors
-- 
2.4.5

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

* [PATCH 02/19] MIPS: Add cases for CPU_I6400
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add a CPU_I6400 case to various switch statements, doing the same thing
as for CPU_P5600.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/cpu-type.h     | 4 ++++
 arch/mips/kernel/idle.c              | 1 +
 arch/mips/kernel/perf_event_mipsxx.c | 6 ++++++
 arch/mips/kernel/pm-cps.c            | 2 ++
 arch/mips/kernel/spram.c             | 1 +
 arch/mips/kernel/traps.c             | 1 +
 arch/mips/mm/c-r4k.c                 | 1 +
 arch/mips/oprofile/common.c          | 1 +
 arch/mips/oprofile/op_model_mipsxx.c | 4 ++++
 9 files changed, 21 insertions(+)

diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h
index d41e8e284825..abee2bfd10dc 100644
--- a/arch/mips/include/asm/cpu-type.h
+++ b/arch/mips/include/asm/cpu-type.h
@@ -77,6 +77,10 @@ static inline int __pure __get_cpu_type(const int cpu_type)
 	 */
 #endif
 
+#ifdef CONFIG_SYS_HAS_CPU_MIPS64_R6
+	case CPU_I6400:
+#endif
+
 #ifdef CONFIG_SYS_HAS_CPU_R3000
 	case CPU_R2000:
 	case CPU_R3000:
diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
index e4f62b7875d2..ab1478d5a4db 100644
--- a/arch/mips/kernel/idle.c
+++ b/arch/mips/kernel/idle.c
@@ -196,6 +196,7 @@ void __init check_wait(void)
 	case CPU_INTERAPTIV:
 	case CPU_M5150:
 	case CPU_QEMU_GENERIC:
+	case CPU_I6400:
 		cpu_wait = r4k_wait;
 		if (read_c0_config7() & MIPS_CONF7_WII)
 			cpu_wait = r4k_wait_irqoff;
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index cc1b6fadf089..d7b8dd43147a 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -1556,6 +1556,7 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
 #endif
 		break;
 	case CPU_P5600:
+	case CPU_I6400:
 		/* 8-bit event numbers */
 		raw_id = config & 0x1ff;
 		base_id = raw_id & 0xff;
@@ -1717,6 +1718,11 @@ init_hw_perf_events(void)
 		mipspmu.general_event_map = &mipsxxcore_event_map2;
 		mipspmu.cache_event_map = &mipsxxcore_cache_map2;
 		break;
+	case CPU_I6400:
+		mipspmu.name = "mips/I6400";
+		mipspmu.general_event_map = &mipsxxcore_event_map2;
+		mipspmu.cache_event_map = &mipsxxcore_cache_map2;
+		break;
 	case CPU_1004K:
 		mipspmu.name = "mips/1004K";
 		mipspmu.general_event_map = &mipsxxcore_event_map;
diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c
index 06147179a175..f63a289977cc 100644
--- a/arch/mips/kernel/pm-cps.c
+++ b/arch/mips/kernel/pm-cps.c
@@ -267,6 +267,7 @@ static int __init cps_gen_flush_fsb(u32 **pp, struct uasm_label **pl,
 
 	/* CPUs which do not require the workaround */
 	case CPU_P5600:
+	case CPU_I6400:
 		return 0;
 
 	default:
@@ -671,6 +672,7 @@ static int __init cps_pm_init(void)
 	case CPU_PROAPTIV:
 	case CPU_M5150:
 	case CPU_P5600:
+	case CPU_I6400:
 		stype_intervention = 0x2;
 		stype_memory = 0x3;
 		stype_ordering = 0x10;
diff --git a/arch/mips/kernel/spram.c b/arch/mips/kernel/spram.c
index d1168d7c31e8..8489c88f9932 100644
--- a/arch/mips/kernel/spram.c
+++ b/arch/mips/kernel/spram.c
@@ -209,6 +209,7 @@ void spram_config(void)
 	case CPU_PROAPTIV:
 	case CPU_P5600:
 	case CPU_QEMU_GENERIC:
+	case CPU_I6400:
 		config0 = read_c0_config();
 		/* FIXME: addresses are Malta specific */
 		if (config0 & (1<<24)) {
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 2a7b38ed23f0..9aa265530b48 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1638,6 +1638,7 @@ static inline void parity_protection_init(void)
 	case CPU_PROAPTIV:
 	case CPU_P5600:
 	case CPU_QEMU_GENERIC:
+	case CPU_I6400:
 		{
 #define ERRCTL_PE	0x80000000
 #define ERRCTL_L2P	0x00800000
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 7f660dc67596..c3e777fc5e8b 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1266,6 +1266,7 @@ static void probe_pcache(void)
 	case CPU_PROAPTIV:
 	case CPU_M5150:
 	case CPU_QEMU_GENERIC:
+	case CPU_I6400:
 		if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
 		    (c->icache.waysize > PAGE_SIZE))
 			c->icache.flags |= MIPS_CACHE_ALIASES;
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index 81f58958cf08..3c9ec3ddca84 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -91,6 +91,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
 	case CPU_INTERAPTIV:
 	case CPU_PROAPTIV:
 	case CPU_P5600:
+	case CPU_I6400:
 	case CPU_M5150:
 	case CPU_LOONGSON1:
 	case CPU_SB1:
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 6a6e2cc55b89..8f988a61b7a8 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -392,6 +392,10 @@ static int __init mipsxx_init(void)
 		op_model_mipsxx_ops.cpu_type = "mips/P5600";
 		break;
 
+	case CPU_I6400:
+		op_model_mipsxx_ops.cpu_type = "mips/I6400";
+		break;
+
 	case CPU_M5150:
 		op_model_mipsxx_ops.cpu_type = "mips/M5150";
 		break;
-- 
2.4.5

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

* [PATCH 02/19] MIPS: Add cases for CPU_I6400
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add a CPU_I6400 case to various switch statements, doing the same thing
as for CPU_P5600.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/cpu-type.h     | 4 ++++
 arch/mips/kernel/idle.c              | 1 +
 arch/mips/kernel/perf_event_mipsxx.c | 6 ++++++
 arch/mips/kernel/pm-cps.c            | 2 ++
 arch/mips/kernel/spram.c             | 1 +
 arch/mips/kernel/traps.c             | 1 +
 arch/mips/mm/c-r4k.c                 | 1 +
 arch/mips/oprofile/common.c          | 1 +
 arch/mips/oprofile/op_model_mipsxx.c | 4 ++++
 9 files changed, 21 insertions(+)

diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h
index d41e8e284825..abee2bfd10dc 100644
--- a/arch/mips/include/asm/cpu-type.h
+++ b/arch/mips/include/asm/cpu-type.h
@@ -77,6 +77,10 @@ static inline int __pure __get_cpu_type(const int cpu_type)
 	 */
 #endif
 
+#ifdef CONFIG_SYS_HAS_CPU_MIPS64_R6
+	case CPU_I6400:
+#endif
+
 #ifdef CONFIG_SYS_HAS_CPU_R3000
 	case CPU_R2000:
 	case CPU_R3000:
diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c
index e4f62b7875d2..ab1478d5a4db 100644
--- a/arch/mips/kernel/idle.c
+++ b/arch/mips/kernel/idle.c
@@ -196,6 +196,7 @@ void __init check_wait(void)
 	case CPU_INTERAPTIV:
 	case CPU_M5150:
 	case CPU_QEMU_GENERIC:
+	case CPU_I6400:
 		cpu_wait = r4k_wait;
 		if (read_c0_config7() & MIPS_CONF7_WII)
 			cpu_wait = r4k_wait_irqoff;
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index cc1b6fadf089..d7b8dd43147a 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -1556,6 +1556,7 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
 #endif
 		break;
 	case CPU_P5600:
+	case CPU_I6400:
 		/* 8-bit event numbers */
 		raw_id = config & 0x1ff;
 		base_id = raw_id & 0xff;
@@ -1717,6 +1718,11 @@ init_hw_perf_events(void)
 		mipspmu.general_event_map = &mipsxxcore_event_map2;
 		mipspmu.cache_event_map = &mipsxxcore_cache_map2;
 		break;
+	case CPU_I6400:
+		mipspmu.name = "mips/I6400";
+		mipspmu.general_event_map = &mipsxxcore_event_map2;
+		mipspmu.cache_event_map = &mipsxxcore_cache_map2;
+		break;
 	case CPU_1004K:
 		mipspmu.name = "mips/1004K";
 		mipspmu.general_event_map = &mipsxxcore_event_map;
diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c
index 06147179a175..f63a289977cc 100644
--- a/arch/mips/kernel/pm-cps.c
+++ b/arch/mips/kernel/pm-cps.c
@@ -267,6 +267,7 @@ static int __init cps_gen_flush_fsb(u32 **pp, struct uasm_label **pl,
 
 	/* CPUs which do not require the workaround */
 	case CPU_P5600:
+	case CPU_I6400:
 		return 0;
 
 	default:
@@ -671,6 +672,7 @@ static int __init cps_pm_init(void)
 	case CPU_PROAPTIV:
 	case CPU_M5150:
 	case CPU_P5600:
+	case CPU_I6400:
 		stype_intervention = 0x2;
 		stype_memory = 0x3;
 		stype_ordering = 0x10;
diff --git a/arch/mips/kernel/spram.c b/arch/mips/kernel/spram.c
index d1168d7c31e8..8489c88f9932 100644
--- a/arch/mips/kernel/spram.c
+++ b/arch/mips/kernel/spram.c
@@ -209,6 +209,7 @@ void spram_config(void)
 	case CPU_PROAPTIV:
 	case CPU_P5600:
 	case CPU_QEMU_GENERIC:
+	case CPU_I6400:
 		config0 = read_c0_config();
 		/* FIXME: addresses are Malta specific */
 		if (config0 & (1<<24)) {
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 2a7b38ed23f0..9aa265530b48 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1638,6 +1638,7 @@ static inline void parity_protection_init(void)
 	case CPU_PROAPTIV:
 	case CPU_P5600:
 	case CPU_QEMU_GENERIC:
+	case CPU_I6400:
 		{
 #define ERRCTL_PE	0x80000000
 #define ERRCTL_L2P	0x00800000
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 7f660dc67596..c3e777fc5e8b 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1266,6 +1266,7 @@ static void probe_pcache(void)
 	case CPU_PROAPTIV:
 	case CPU_M5150:
 	case CPU_QEMU_GENERIC:
+	case CPU_I6400:
 		if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
 		    (c->icache.waysize > PAGE_SIZE))
 			c->icache.flags |= MIPS_CACHE_ALIASES;
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index 81f58958cf08..3c9ec3ddca84 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -91,6 +91,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
 	case CPU_INTERAPTIV:
 	case CPU_PROAPTIV:
 	case CPU_P5600:
+	case CPU_I6400:
 	case CPU_M5150:
 	case CPU_LOONGSON1:
 	case CPU_SB1:
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 6a6e2cc55b89..8f988a61b7a8 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -392,6 +392,10 @@ static int __init mipsxx_init(void)
 		op_model_mipsxx_ops.cpu_type = "mips/P5600";
 		break;
 
+	case CPU_I6400:
+		op_model_mipsxx_ops.cpu_type = "mips/I6400";
+		break;
+
 	case CPU_M5150:
 		op_model_mipsxx_ops.cpu_type = "mips/M5150";
 		break;
-- 
2.4.5

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

* [PATCH 03/19] MIPS: Add MIPS I6400 probe support
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add a case in cpu_probe_mips for the MIPS I6400 processor ID, which sets
the CPU type to the new CPU_I6400.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cpu-probe.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index dbe0792fc9c1..02b75127dad3 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -1121,6 +1121,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
 		c->cputype = CPU_P5600;
 		__cpu_name[cpu] = "MIPS P5600";
 		break;
+	case PRID_IMP_I6400:
+		c->cputype = CPU_I6400;
+		__cpu_name[cpu] = "MIPS I6400";
+		break;
 	case PRID_IMP_M5150:
 		c->cputype = CPU_M5150;
 		__cpu_name[cpu] = "MIPS M5150";
-- 
2.4.5

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

* [PATCH 03/19] MIPS: Add MIPS I6400 probe support
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add a case in cpu_probe_mips for the MIPS I6400 processor ID, which sets
the CPU type to the new CPU_I6400.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cpu-probe.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index dbe0792fc9c1..02b75127dad3 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -1121,6 +1121,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
 		c->cputype = CPU_P5600;
 		__cpu_name[cpu] = "MIPS P5600";
 		break;
+	case PRID_IMP_I6400:
+		c->cputype = CPU_I6400;
+		__cpu_name[cpu] = "MIPS I6400";
+		break;
 	case PRID_IMP_M5150:
 		c->cputype = CPU_M5150;
 		__cpu_name[cpu] = "MIPS M5150";
-- 
2.4.5

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

* [PATCH 04/19] MIPS: Kconfig: Disable MIPS MT and SMP implementations for R6
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

R6 does not support the MIPS MT ASE and the CMP/SMP options so
restrict them in order to prevent users from selecting incompatible
SMP configuration for R6 cores. We also disable the CPS/SMP option
because its support hasn't been added to the CPS code yet.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/Kconfig | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 2a14585c90d2..51bc4873e7e8 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2113,7 +2113,7 @@ config CPU_R4K_CACHE_TLB
 
 config MIPS_MT_SMP
 	bool "MIPS MT SMP support (1 TC on each available VPE)"
-	depends on SYS_SUPPORTS_MULTITHREADING
+	depends on SYS_SUPPORTS_MULTITHREADING && !CPU_MIPSR6
 	select CPU_MIPSR2_IRQ_VI
 	select CPU_MIPSR2_IRQ_EI
 	select SYNC_R4K
@@ -2214,7 +2214,7 @@ config MIPS_VPE_APSP_API_MT
 
 config MIPS_CMP
 	bool "MIPS CMP framework support (DEPRECATED)"
-	depends on SYS_SUPPORTS_MIPS_CMP
+	depends on SYS_SUPPORTS_MIPS_CMP && !CPU_MIPSR6
 	select MIPS_GIC_IPI
 	select SMP
 	select SYNC_R4K
@@ -2231,7 +2231,7 @@ config MIPS_CMP
 
 config MIPS_CPS
 	bool "MIPS Coherent Processing System support"
-	depends on SYS_SUPPORTS_MIPS_CPS && !64BIT
+	depends on SYS_SUPPORTS_MIPS_CPS && !64BIT && !CPU_MIPSR6
 	select MIPS_CM
 	select MIPS_CPC
 	select MIPS_CPS_PM if HOTPLUG_CPU
-- 
2.4.5

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

* [PATCH 04/19] MIPS: Kconfig: Disable MIPS MT and SMP implementations for R6
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

R6 does not support the MIPS MT ASE and the CMP/SMP options so
restrict them in order to prevent users from selecting incompatible
SMP configuration for R6 cores. We also disable the CPS/SMP option
because its support hasn't been added to the CPS code yet.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/Kconfig | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 2a14585c90d2..51bc4873e7e8 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2113,7 +2113,7 @@ config CPU_R4K_CACHE_TLB
 
 config MIPS_MT_SMP
 	bool "MIPS MT SMP support (1 TC on each available VPE)"
-	depends on SYS_SUPPORTS_MULTITHREADING
+	depends on SYS_SUPPORTS_MULTITHREADING && !CPU_MIPSR6
 	select CPU_MIPSR2_IRQ_VI
 	select CPU_MIPSR2_IRQ_EI
 	select SYNC_R4K
@@ -2214,7 +2214,7 @@ config MIPS_VPE_APSP_API_MT
 
 config MIPS_CMP
 	bool "MIPS CMP framework support (DEPRECATED)"
-	depends on SYS_SUPPORTS_MIPS_CMP
+	depends on SYS_SUPPORTS_MIPS_CMP && !CPU_MIPSR6
 	select MIPS_GIC_IPI
 	select SMP
 	select SYNC_R4K
@@ -2231,7 +2231,7 @@ config MIPS_CMP
 
 config MIPS_CPS
 	bool "MIPS Coherent Processing System support"
-	depends on SYS_SUPPORTS_MIPS_CPS && !64BIT
+	depends on SYS_SUPPORTS_MIPS_CPS && !64BIT && !CPU_MIPSR6
 	select MIPS_CM
 	select MIPS_CPC
 	select MIPS_CPS_PM if HOTPLUG_CPU
-- 
2.4.5

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

* [PATCH 05/19] MIPS: asm: mips-cm: Implement mips_cm_revision
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Markos Chandras

From: Paul Burton <paul.burton@imgtec.com>

Provide a function to trivially return the version of the CM present in
the system, or 0 if no CM is present. The mips_cm_revision() will be
used later on to determine the CM register width, so it must not use
the regular CM accessors to read the revision register since that will
lead to build failures due to recursive inlines.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/mips-cm.h | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index edc7ee95269e..29ff74a629f6 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -189,6 +189,13 @@ BUILD_CM_Cx_R_(tcid_8_priority,	0x80)
 #define CM_GCR_REV_MINOR_SHF			0
 #define CM_GCR_REV_MINOR_MSK			(_ULCAST_(0xff) << 0)
 
+#define CM_ENCODE_REV(major, minor) \
+		((major << CM_GCR_REV_MAJOR_SHF) | \
+		 ((minor) << CM_GCR_REV_MINOR_SHF))
+
+#define CM_REV_CM2				CM_ENCODE_REV(6, 0)
+#define CM_REV_CM3				CM_ENCODE_REV(8, 0)
+
 /* GCR_ERROR_CAUSE register fields */
 #define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF		27
 #define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK		(_ULCAST_(0x1f) << 27)
@@ -324,4 +331,26 @@ static inline int mips_cm_l2sync(void)
 	return 0;
 }
 
+/**
+ * mips_cm_revision - return CM revision
+ *
+ * Returns the revision of the CM, from GCR_REV, or 0 if no CM is present.
+ * The return value should be checked against the CM_REV_* macros.
+ */
+static inline int mips_cm_revision(void)
+{
+	static int mips_cm_revision_nr = -1;
+
+	/* No need to read that register over and over */
+	if (mips_cm_revision_nr >= 0)
+		return mips_cm_revision_nr;
+
+	if (!mips_cm_present())
+		return 0;
+
+	mips_cm_revision_nr = read_gcr_rev();
+
+	return mips_cm_revision_nr;
+}
+
 #endif /* __MIPS_ASM_MIPS_CM_H__ */
-- 
2.4.5

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

* [PATCH 05/19] MIPS: asm: mips-cm: Implement mips_cm_revision
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Markos Chandras

From: Paul Burton <paul.burton@imgtec.com>

Provide a function to trivially return the version of the CM present in
the system, or 0 if no CM is present. The mips_cm_revision() will be
used later on to determine the CM register width, so it must not use
the regular CM accessors to read the revision register since that will
lead to build failures due to recursive inlines.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/mips-cm.h | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index edc7ee95269e..29ff74a629f6 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -189,6 +189,13 @@ BUILD_CM_Cx_R_(tcid_8_priority,	0x80)
 #define CM_GCR_REV_MINOR_SHF			0
 #define CM_GCR_REV_MINOR_MSK			(_ULCAST_(0xff) << 0)
 
+#define CM_ENCODE_REV(major, minor) \
+		((major << CM_GCR_REV_MAJOR_SHF) | \
+		 ((minor) << CM_GCR_REV_MINOR_SHF))
+
+#define CM_REV_CM2				CM_ENCODE_REV(6, 0)
+#define CM_REV_CM3				CM_ENCODE_REV(8, 0)
+
 /* GCR_ERROR_CAUSE register fields */
 #define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF		27
 #define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK		(_ULCAST_(0x1f) << 27)
@@ -324,4 +331,26 @@ static inline int mips_cm_l2sync(void)
 	return 0;
 }
 
+/**
+ * mips_cm_revision - return CM revision
+ *
+ * Returns the revision of the CM, from GCR_REV, or 0 if no CM is present.
+ * The return value should be checked against the CM_REV_* macros.
+ */
+static inline int mips_cm_revision(void)
+{
+	static int mips_cm_revision_nr = -1;
+
+	/* No need to read that register over and over */
+	if (mips_cm_revision_nr >= 0)
+		return mips_cm_revision_nr;
+
+	if (!mips_cm_present())
+		return 0;
+
+	mips_cm_revision_nr = read_gcr_rev();
+
+	return mips_cm_revision_nr;
+}
+
 #endif /* __MIPS_ASM_MIPS_CM_H__ */
-- 
2.4.5

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

* [PATCH 06/19] MIPS: asm: add CM GCR_L2_CONFIG register accessors
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Markos Chandras

From: Paul Burton <paul.burton@imgtec.com>

Provide accessor functions for the GCR_L2_CONFIG register introduced
with CM3, and define the bits included in the register.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/mips-cm.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index 29ff74a629f6..a832de2739ad 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -144,6 +144,7 @@ BUILD_CM_RW(reg3_base,		MIPS_CM_GCB_OFS + 0xc0)
 BUILD_CM_RW(reg3_mask,		MIPS_CM_GCB_OFS + 0xc8)
 BUILD_CM_R_(gic_status,		MIPS_CM_GCB_OFS + 0xd0)
 BUILD_CM_R_(cpc_status,		MIPS_CM_GCB_OFS + 0xf0)
+BUILD_CM_RW(l2_config,		MIPS_CM_GCB_OFS + 0x130)
 
 /* Core Local & Core Other register accessor functions */
 BUILD_CM_Cx_RW(reset_release,	0x00)
@@ -256,6 +257,16 @@ BUILD_CM_Cx_R_(tcid_8_priority,	0x80)
 #define CM_GCR_CPC_STATUS_EX_SHF		0
 #define CM_GCR_CPC_STATUS_EX_MSK		(_ULCAST_(0x1) << 0)
 
+/* GCR_L2_CONFIG register fields */
+#define CM_GCR_L2_CONFIG_BYPASS_SHF		20
+#define CM_GCR_L2_CONFIG_BYPASS_MSK		(_ULCAST_(0x1) << 20)
+#define CM_GCR_L2_CONFIG_SET_SIZE_SHF		12
+#define CM_GCR_L2_CONFIG_SET_SIZE_MSK		(_ULCAST_(0xf) << 12)
+#define CM_GCR_L2_CONFIG_LINE_SIZE_SHF		8
+#define CM_GCR_L2_CONFIG_LINE_SIZE_MSK		(_ULCAST_(0xf) << 8)
+#define CM_GCR_L2_CONFIG_ASSOC_SHF		0
+#define CM_GCR_L2_CONFIG_ASSOC_MSK		(_ULCAST_(0xff) << 0)
+
 /* GCR_Cx_COHERENCE register fields */
 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_SHF	0
 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK	(_ULCAST_(0xff) << 0)
-- 
2.4.5

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

* [PATCH 06/19] MIPS: asm: add CM GCR_L2_CONFIG register accessors
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Markos Chandras

From: Paul Burton <paul.burton@imgtec.com>

Provide accessor functions for the GCR_L2_CONFIG register introduced
with CM3, and define the bits included in the register.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/mips-cm.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index 29ff74a629f6..a832de2739ad 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -144,6 +144,7 @@ BUILD_CM_RW(reg3_base,		MIPS_CM_GCB_OFS + 0xc0)
 BUILD_CM_RW(reg3_mask,		MIPS_CM_GCB_OFS + 0xc8)
 BUILD_CM_R_(gic_status,		MIPS_CM_GCB_OFS + 0xd0)
 BUILD_CM_R_(cpc_status,		MIPS_CM_GCB_OFS + 0xf0)
+BUILD_CM_RW(l2_config,		MIPS_CM_GCB_OFS + 0x130)
 
 /* Core Local & Core Other register accessor functions */
 BUILD_CM_Cx_RW(reset_release,	0x00)
@@ -256,6 +257,16 @@ BUILD_CM_Cx_R_(tcid_8_priority,	0x80)
 #define CM_GCR_CPC_STATUS_EX_SHF		0
 #define CM_GCR_CPC_STATUS_EX_MSK		(_ULCAST_(0x1) << 0)
 
+/* GCR_L2_CONFIG register fields */
+#define CM_GCR_L2_CONFIG_BYPASS_SHF		20
+#define CM_GCR_L2_CONFIG_BYPASS_MSK		(_ULCAST_(0x1) << 20)
+#define CM_GCR_L2_CONFIG_SET_SIZE_SHF		12
+#define CM_GCR_L2_CONFIG_SET_SIZE_MSK		(_ULCAST_(0xf) << 12)
+#define CM_GCR_L2_CONFIG_LINE_SIZE_SHF		8
+#define CM_GCR_L2_CONFIG_LINE_SIZE_MSK		(_ULCAST_(0xf) << 8)
+#define CM_GCR_L2_CONFIG_ASSOC_SHF		0
+#define CM_GCR_L2_CONFIG_ASSOC_MSK		(_ULCAST_(0xff) << 0)
+
 /* GCR_Cx_COHERENCE register fields */
 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_SHF	0
 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK	(_ULCAST_(0xff) << 0)
-- 
2.4.5

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

* [PATCH 07/19] MIPS: mm: c-r4k: extend way_string array
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Markos Chandras

From: Paul Burton <paul.burton@imgtec.com>

The L2 cache in the I6400 core has 16 ways, so extend the way_string
array to take such caches into account.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mm/c-r4k.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index c3e777fc5e8b..a9867c3222b1 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -937,7 +937,9 @@ static void b5k_instruction_hazard(void)
 }
 
 static char *way_string[] = { NULL, "direct mapped", "2-way",
-	"3-way", "4-way", "5-way", "6-way", "7-way", "8-way"
+	"3-way", "4-way", "5-way", "6-way", "7-way", "8-way",
+	"9-way", "10-way", "11-way", "12-way",
+	"13-way", "14-way", "15-way", "16-way",
 };
 
 static void probe_pcache(void)
-- 
2.4.5

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

* [PATCH 07/19] MIPS: mm: c-r4k: extend way_string array
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Markos Chandras

From: Paul Burton <paul.burton@imgtec.com>

The L2 cache in the I6400 core has 16 ways, so extend the way_string
array to take such caches into account.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mm/c-r4k.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index c3e777fc5e8b..a9867c3222b1 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -937,7 +937,9 @@ static void b5k_instruction_hazard(void)
 }
 
 static char *way_string[] = { NULL, "direct mapped", "2-way",
-	"3-way", "4-way", "5-way", "6-way", "7-way", "8-way"
+	"3-way", "4-way", "5-way", "6-way", "7-way", "8-way",
+	"9-way", "10-way", "11-way", "12-way",
+	"13-way", "14-way", "15-way", "16-way",
 };
 
 static void probe_pcache(void)
-- 
2.4.5

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

* [PATCH 08/19] MIPS: support CM3 L2 cache
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Markos Chandras

From: Paul Burton <paul.burton@imgtec.com>

Detect the L2 cache configuration from GCR_L2_CONFIG when a CM3 is
present in the system, rather than from Config2 which does not expose
the L2 configuration on I6400.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mm/sc-mips.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c
index 4ceafd13870c..5fa452e8cff9 100644
--- a/arch/mips/mm/sc-mips.c
+++ b/arch/mips/mm/sc-mips.c
@@ -14,6 +14,7 @@
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 #include <asm/r4kcache.h>
+#include <asm/mips-cm.h>
 
 /*
  * MIPS32/MIPS64 L2 cache handling
@@ -94,6 +95,34 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
 	return 1;
 }
 
+static int __init mips_sc_probe_cm3(void)
+{
+	struct cpuinfo_mips *c = &current_cpu_data;
+	unsigned long cfg = read_gcr_l2_config();
+	unsigned long sets, line_sz, assoc;
+
+	if (cfg & CM_GCR_L2_CONFIG_BYPASS_MSK)
+		return 0;
+
+	sets = cfg & CM_GCR_L2_CONFIG_SET_SIZE_MSK;
+	sets >>= CM_GCR_L2_CONFIG_SET_SIZE_SHF;
+	c->scache.sets = 64 << sets;
+
+	line_sz = cfg & CM_GCR_L2_CONFIG_LINE_SIZE_MSK;
+	line_sz >>= CM_GCR_L2_CONFIG_LINE_SIZE_SHF;
+	c->scache.linesz = 2 << line_sz;
+
+	assoc = cfg & CM_GCR_L2_CONFIG_ASSOC_MSK;
+	assoc >>= CM_GCR_L2_CONFIG_ASSOC_SHF;
+	c->scache.ways = assoc + 1;
+	c->scache.waysize = c->scache.sets * c->scache.linesz;
+	c->scache.waybit = __ffs(c->scache.waysize);
+
+	c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
+
+	return 1;
+}
+
 static inline int __init mips_sc_probe(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
@@ -103,6 +132,9 @@ static inline int __init mips_sc_probe(void)
 	/* Mark as not present until probe completed */
 	c->scache.flags |= MIPS_CACHE_NOT_PRESENT;
 
+	if (mips_cm_revision() >= CM_REV_CM3)
+		return mips_sc_probe_cm3();
+
 	/* Ignore anything but MIPSxx processors */
 	if (!(c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
 			      MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
-- 
2.4.5

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

* [PATCH 08/19] MIPS: support CM3 L2 cache
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Markos Chandras

From: Paul Burton <paul.burton@imgtec.com>

Detect the L2 cache configuration from GCR_L2_CONFIG when a CM3 is
present in the system, rather than from Config2 which does not expose
the L2 configuration on I6400.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/mm/sc-mips.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c
index 4ceafd13870c..5fa452e8cff9 100644
--- a/arch/mips/mm/sc-mips.c
+++ b/arch/mips/mm/sc-mips.c
@@ -14,6 +14,7 @@
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 #include <asm/r4kcache.h>
+#include <asm/mips-cm.h>
 
 /*
  * MIPS32/MIPS64 L2 cache handling
@@ -94,6 +95,34 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
 	return 1;
 }
 
+static int __init mips_sc_probe_cm3(void)
+{
+	struct cpuinfo_mips *c = &current_cpu_data;
+	unsigned long cfg = read_gcr_l2_config();
+	unsigned long sets, line_sz, assoc;
+
+	if (cfg & CM_GCR_L2_CONFIG_BYPASS_MSK)
+		return 0;
+
+	sets = cfg & CM_GCR_L2_CONFIG_SET_SIZE_MSK;
+	sets >>= CM_GCR_L2_CONFIG_SET_SIZE_SHF;
+	c->scache.sets = 64 << sets;
+
+	line_sz = cfg & CM_GCR_L2_CONFIG_LINE_SIZE_MSK;
+	line_sz >>= CM_GCR_L2_CONFIG_LINE_SIZE_SHF;
+	c->scache.linesz = 2 << line_sz;
+
+	assoc = cfg & CM_GCR_L2_CONFIG_ASSOC_MSK;
+	assoc >>= CM_GCR_L2_CONFIG_ASSOC_SHF;
+	c->scache.ways = assoc + 1;
+	c->scache.waysize = c->scache.sets * c->scache.linesz;
+	c->scache.waybit = __ffs(c->scache.waysize);
+
+	c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
+
+	return 1;
+}
+
 static inline int __init mips_sc_probe(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
@@ -103,6 +132,9 @@ static inline int __init mips_sc_probe(void)
 	/* Mark as not present until probe completed */
 	c->scache.flags |= MIPS_CACHE_NOT_PRESENT;
 
+	if (mips_cm_revision() >= CM_REV_CM3)
+		return mips_sc_probe_cm3();
+
 	/* Ignore anything but MIPSxx processors */
 	if (!(c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
 			      MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |
-- 
2.4.5

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

* [PATCH 09/19] MIPS: Add platform callback before initializing the L2 cache
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Paul Burton

Allow platforms to perform platform-specific steps before configuring
the L2 cache. This is necessary for platforms with CM3 since the L2
parameters no longer live in the Config2 register.

Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/mips-cm.c       |  7 +++++++
 arch/mips/mm/sc-mips.c           | 10 ++++++++++
 arch/mips/mti-malta/malta-init.c |  7 +++++++
 3 files changed, 24 insertions(+)

diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 85bbe9b96759..42602f30949f 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -81,6 +81,13 @@ int mips_cm_probe(void)
 	phys_addr_t addr;
 	u32 base_reg;
 
+	/*
+	 * No need to probe again if we have already been
+	 * here before.
+	 */
+	if (mips_cm_base)
+		return 0;
+
 	addr = mips_cm_phys_base();
 	BUG_ON((addr & CM_GCR_BASE_GCRBASE_MSK) != addr);
 	if (!addr)
diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c
index 5fa452e8cff9..53ea8391f9bb 100644
--- a/arch/mips/mm/sc-mips.c
+++ b/arch/mips/mm/sc-mips.c
@@ -123,6 +123,10 @@ static int __init mips_sc_probe_cm3(void)
 	return 1;
 }
 
+void __weak platform_early_l2_init(void)
+{
+}
+
 static inline int __init mips_sc_probe(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
@@ -132,6 +136,12 @@ static inline int __init mips_sc_probe(void)
 	/* Mark as not present until probe completed */
 	c->scache.flags |= MIPS_CACHE_NOT_PRESENT;
 
+	/*
+	 * Do we need some platform specific probing before
+	 * we configure L2?
+	 */
+	platform_early_l2_init();
+
 	if (mips_cm_revision() >= CM_REV_CM3)
 		return mips_sc_probe_cm3();
 
diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c
index cec3e187c48f..53c24784a2f7 100644
--- a/arch/mips/mti-malta/malta-init.c
+++ b/arch/mips/mti-malta/malta-init.c
@@ -303,3 +303,10 @@ mips_pci_controller:
 	if (!register_vsmp_smp_ops())
 		return;
 }
+
+void platform_early_l2_init(void)
+{
+	/* L2 configuration lives in the CM3 */
+	if (mips_cm_revision() >= CM_REV_CM3)
+		mips_cm_probe();
+}
-- 
2.4.5

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

* [PATCH 09/19] MIPS: Add platform callback before initializing the L2 cache
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Paul Burton

Allow platforms to perform platform-specific steps before configuring
the L2 cache. This is necessary for platforms with CM3 since the L2
parameters no longer live in the Config2 register.

Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/mips-cm.c       |  7 +++++++
 arch/mips/mm/sc-mips.c           | 10 ++++++++++
 arch/mips/mti-malta/malta-init.c |  7 +++++++
 3 files changed, 24 insertions(+)

diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 85bbe9b96759..42602f30949f 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -81,6 +81,13 @@ int mips_cm_probe(void)
 	phys_addr_t addr;
 	u32 base_reg;
 
+	/*
+	 * No need to probe again if we have already been
+	 * here before.
+	 */
+	if (mips_cm_base)
+		return 0;
+
 	addr = mips_cm_phys_base();
 	BUG_ON((addr & CM_GCR_BASE_GCRBASE_MSK) != addr);
 	if (!addr)
diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c
index 5fa452e8cff9..53ea8391f9bb 100644
--- a/arch/mips/mm/sc-mips.c
+++ b/arch/mips/mm/sc-mips.c
@@ -123,6 +123,10 @@ static int __init mips_sc_probe_cm3(void)
 	return 1;
 }
 
+void __weak platform_early_l2_init(void)
+{
+}
+
 static inline int __init mips_sc_probe(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
@@ -132,6 +136,12 @@ static inline int __init mips_sc_probe(void)
 	/* Mark as not present until probe completed */
 	c->scache.flags |= MIPS_CACHE_NOT_PRESENT;
 
+	/*
+	 * Do we need some platform specific probing before
+	 * we configure L2?
+	 */
+	platform_early_l2_init();
+
 	if (mips_cm_revision() >= CM_REV_CM3)
 		return mips_sc_probe_cm3();
 
diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c
index cec3e187c48f..53c24784a2f7 100644
--- a/arch/mips/mti-malta/malta-init.c
+++ b/arch/mips/mti-malta/malta-init.c
@@ -303,3 +303,10 @@ mips_pci_controller:
 	if (!register_vsmp_smp_ops())
 		return;
 }
+
+void platform_early_l2_init(void)
+{
+	/* L2 configuration lives in the CM3 */
+	if (mips_cm_revision() >= CM_REV_CM3)
+		mips_cm_probe();
+}
-- 
2.4.5

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

* [PATCH 10/19] MIPS: asm: mips-cm: Extend CM accessors for 64-bit CPUs
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips
  Cc: Markos Chandras, Thomas Gleixner, Jason Cooper, Andrew Bresticker,
	Paul Burton

Previously, the CM accessors were only accessing CM registers as u32
types instead of using the native CM register with. However, newer CMs
may actually be 64-bit on MIPS64 cores. Fortunately, current 64-bit CMs
(CM3) hold all the useful configuration bits in the lower half of the
64-bit registers (at least most of them) so they can still be accessed
using the current 32-bit accessors. However, accessing the CM registers
using their native width can result to performance improvements since
only one instruction is used to read/write them instead of treating
them as register pairs. This is mostly true for CM components like GIC
and CPC but for consistency reasons we do the same thing on the CM
registers as well.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Bresticker <abrestic@chromium.org>
Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/mips-cm.h | 48 +++++++++++++++++++++++++++++++++++++----
 arch/mips/kernel/mips-cm.c      |  4 ++++
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index a832de2739ad..273b89a685d5 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -33,6 +33,20 @@ extern void __iomem *mips_cm_l2sync_base;
  */
 extern phys_addr_t __mips_cm_phys_base(void);
 
+/*
+ * mips_cm_is64 - determine CM register width
+ *
+ * The CM register width is processor and CM specific. A 64-bit processor
+ * usually has a 64-bit CM and a 32-bit one has a 32-bit CM but a 64-bit
+ * processor could come with a 32-bit CM. Moreover, accesses on 64-bit CMs
+ * can be done either using regular 64-bit load/store instructions, or 32-bit
+ * load/store instruction on 32-bit register pairs. We opt for using 64-bit
+ * accesses on 64-bit CMs and processors and 32-bit in any other case.
+ *
+ * It's set to 0 for 32-bit accesses and 1 for 64-bit accesses.
+ */
+extern int mips_cm_is64;
+
 /**
  * mips_cm_probe - probe for a Coherence Manager
  *
@@ -90,20 +104,46 @@ static inline bool mips_cm_has_l2sync(void)
 
 /* Macros to ease the creation of register access functions */
 #define BUILD_CM_R_(name, off)					\
-static inline u32 __iomem *addr_gcr_##name(void)		\
+static inline unsigned long __iomem *addr_gcr_##name(void)	\
 {								\
-	return (u32 __iomem *)(mips_cm_base + (off));		\
+	return (unsigned long __iomem *)(mips_cm_base + (off));	\
 }								\
 								\
-static inline u32 read_gcr_##name(void)				\
+static inline u32 read32_gcr_##name(void)			\
 {								\
 	return __raw_readl(addr_gcr_##name());			\
+}								\
+								\
+static inline u64 read64_gcr_##name(void)			\
+{								\
+	return __raw_readq(addr_gcr_##name());			\
+}								\
+								\
+static inline unsigned long read_gcr_##name(void)		\
+{								\
+	if (mips_cm_is64)					\
+		return read64_gcr_##name();			\
+	else							\
+		return read32_gcr_##name();			\
 }
 
 #define BUILD_CM__W(name, off)					\
-static inline void write_gcr_##name(u32 value)			\
+static inline void write32_gcr_##name(u32 value)		\
 {								\
 	__raw_writel(value, addr_gcr_##name());			\
+}								\
+								\
+static inline void write64_gcr_##name(u64 value)		\
+{								\
+	__raw_writeq(value, addr_gcr_##name());			\
+}								\
+								\
+static inline void write_gcr_##name(unsigned long value)	\
+{								\
+	if (mips_cm_is64)					\
+		write64_gcr_##name(value);			\
+	else							\
+		write32_gcr_##name(value);			\
 }
 
 #define BUILD_CM_RW(name, off)					\
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 42602f30949f..7e460e09661a 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -15,6 +15,7 @@
 
 void __iomem *mips_cm_base;
 void __iomem *mips_cm_l2sync_base;
+int mips_cm_is64;
 
 phys_addr_t __mips_cm_phys_base(void)
 {
@@ -124,5 +125,8 @@ int mips_cm_probe(void)
 	/* probe for an L2-only sync region */
 	mips_cm_probe_l2sync();
 
+	/* determine register width for this CM */
+	mips_cm_is64 = cpu_has_64bits && (mips_cm_revision() >= CM_REV_CM3);
+
 	return 0;
 }
-- 
2.4.5

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

* [PATCH 10/19] MIPS: asm: mips-cm: Extend CM accessors for 64-bit CPUs
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips
  Cc: Markos Chandras, Thomas Gleixner, Jason Cooper, Andrew Bresticker,
	Paul Burton

Previously, the CM accessors were only accessing CM registers as u32
types instead of using the native CM register with. However, newer CMs
may actually be 64-bit on MIPS64 cores. Fortunately, current 64-bit CMs
(CM3) hold all the useful configuration bits in the lower half of the
64-bit registers (at least most of them) so they can still be accessed
using the current 32-bit accessors. However, accessing the CM registers
using their native width can result to performance improvements since
only one instruction is used to read/write them instead of treating
them as register pairs. This is mostly true for CM components like GIC
and CPC but for consistency reasons we do the same thing on the CM
registers as well.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Bresticker <abrestic@chromium.org>
Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/mips-cm.h | 48 +++++++++++++++++++++++++++++++++++++----
 arch/mips/kernel/mips-cm.c      |  4 ++++
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index a832de2739ad..273b89a685d5 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -33,6 +33,20 @@ extern void __iomem *mips_cm_l2sync_base;
  */
 extern phys_addr_t __mips_cm_phys_base(void);
 
+/*
+ * mips_cm_is64 - determine CM register width
+ *
+ * The CM register width is processor and CM specific. A 64-bit processor
+ * usually has a 64-bit CM and a 32-bit one has a 32-bit CM but a 64-bit
+ * processor could come with a 32-bit CM. Moreover, accesses on 64-bit CMs
+ * can be done either using regular 64-bit load/store instructions, or 32-bit
+ * load/store instruction on 32-bit register pairs. We opt for using 64-bit
+ * accesses on 64-bit CMs and processors and 32-bit in any other case.
+ *
+ * It's set to 0 for 32-bit accesses and 1 for 64-bit accesses.
+ */
+extern int mips_cm_is64;
+
 /**
  * mips_cm_probe - probe for a Coherence Manager
  *
@@ -90,20 +104,46 @@ static inline bool mips_cm_has_l2sync(void)
 
 /* Macros to ease the creation of register access functions */
 #define BUILD_CM_R_(name, off)					\
-static inline u32 __iomem *addr_gcr_##name(void)		\
+static inline unsigned long __iomem *addr_gcr_##name(void)	\
 {								\
-	return (u32 __iomem *)(mips_cm_base + (off));		\
+	return (unsigned long __iomem *)(mips_cm_base + (off));	\
 }								\
 								\
-static inline u32 read_gcr_##name(void)				\
+static inline u32 read32_gcr_##name(void)			\
 {								\
 	return __raw_readl(addr_gcr_##name());			\
+}								\
+								\
+static inline u64 read64_gcr_##name(void)			\
+{								\
+	return __raw_readq(addr_gcr_##name());			\
+}								\
+								\
+static inline unsigned long read_gcr_##name(void)		\
+{								\
+	if (mips_cm_is64)					\
+		return read64_gcr_##name();			\
+	else							\
+		return read32_gcr_##name();			\
 }
 
 #define BUILD_CM__W(name, off)					\
-static inline void write_gcr_##name(u32 value)			\
+static inline void write32_gcr_##name(u32 value)		\
 {								\
 	__raw_writel(value, addr_gcr_##name());			\
+}								\
+								\
+static inline void write64_gcr_##name(u64 value)		\
+{								\
+	__raw_writeq(value, addr_gcr_##name());			\
+}								\
+								\
+static inline void write_gcr_##name(unsigned long value)	\
+{								\
+	if (mips_cm_is64)					\
+		write64_gcr_##name(value);			\
+	else							\
+		write32_gcr_##name(value);			\
 }
 
 #define BUILD_CM_RW(name, off)					\
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 42602f30949f..7e460e09661a 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -15,6 +15,7 @@
 
 void __iomem *mips_cm_base;
 void __iomem *mips_cm_l2sync_base;
+int mips_cm_is64;
 
 phys_addr_t __mips_cm_phys_base(void)
 {
@@ -124,5 +125,8 @@ int mips_cm_probe(void)
 	/* probe for an L2-only sync region */
 	mips_cm_probe_l2sync();
 
+	/* determine register width for this CM */
+	mips_cm_is64 = cpu_has_64bits && (mips_cm_revision() >= CM_REV_CM3);
+
 	return 0;
 }
-- 
2.4.5

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

* [PATCH 11/19] MIPS: kernel: mips-cm: The CMGCRBase register is 64-bit on MIPS64
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Paul Burton

The CMGCRBase register (CP0, 15, 3) register is 64-bit on MIPS64
so we change its type to unsigned long.

Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/mips-cm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 7e460e09661a..37a9885ef0da 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -20,7 +20,7 @@ int mips_cm_is64;
 phys_addr_t __mips_cm_phys_base(void)
 {
 	u32 config3 = read_c0_config3();
-	u32 cmgcr;
+	unsigned long cmgcr;
 
 	/* Check the CMGCRBase register is implemented */
 	if (!(config3 & MIPS_CONF3_CMGCR))
-- 
2.4.5

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

* [PATCH 11/19] MIPS: kernel: mips-cm: The CMGCRBase register is 64-bit on MIPS64
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras, Paul Burton

The CMGCRBase register (CP0, 15, 3) register is 64-bit on MIPS64
so we change its type to unsigned long.

Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/mips-cm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 7e460e09661a..37a9885ef0da 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -20,7 +20,7 @@ int mips_cm_is64;
 phys_addr_t __mips_cm_phys_base(void)
 {
 	u32 config3 = read_c0_config3();
-	u32 cmgcr;
+	unsigned long cmgcr;
 
 	/* Check the CMGCRBase register is implemented */
 	if (!(config3 & MIPS_CONF3_CMGCR))
-- 
2.4.5

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

* [PATCH 12/19] MIPS: kernel: mips-cpc: Fix type for GCR CPC base reg for 64-bit
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The GCR CPC base register is 64-bit on 64-bit processors so use the
appropriate field.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/mips-cpc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/kernel/mips-cpc.c b/arch/mips/kernel/mips-cpc.c
index 11964501c4b0..e05aca41e087 100644
--- a/arch/mips/kernel/mips-cpc.c
+++ b/arch/mips/kernel/mips-cpc.c
@@ -23,7 +23,7 @@ static DEFINE_PER_CPU_ALIGNED(unsigned long, cpc_core_lock_flags);
 
 phys_addr_t __weak mips_cpc_phys_base(void)
 {
-	u32 cpc_base;
+	unsigned long cpc_base;
 
 	if (!mips_cm_present())
 		return 0;
-- 
2.4.5

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

* [PATCH 12/19] MIPS: kernel: mips-cpc: Fix type for GCR CPC base reg for 64-bit
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The GCR CPC base register is 64-bit on 64-bit processors so use the
appropriate field.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/mips-cpc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/kernel/mips-cpc.c b/arch/mips/kernel/mips-cpc.c
index 11964501c4b0..e05aca41e087 100644
--- a/arch/mips/kernel/mips-cpc.c
+++ b/arch/mips/kernel/mips-cpc.c
@@ -23,7 +23,7 @@ static DEFINE_PER_CPU_ALIGNED(unsigned long, cpc_core_lock_flags);
 
 phys_addr_t __weak mips_cpc_phys_base(void)
 {
-	u32 cpc_base;
+	unsigned long cpc_base;
 
 	if (!mips_cm_present())
 		return 0;
-- 
2.4.5

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

* [PATCH 13/19] MIPS: kernel: mips-cm: Add support for reporting CM cache errors
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The CM cache error reporting code is not Malta specific and as such it
should live in the mips-cm.c file. Moreover, CM2 and CM3 differ in the
way cache errors are being recorded to the registers so extend the
previous code to add support for the CM3 as well.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/mips-cm.h |   9 ++
 arch/mips/kernel/mips-cm.c      | 244 ++++++++++++++++++++++++++++++++++++++++
 arch/mips/mti-malta/malta-int.c | 112 +-----------------
 3 files changed, 254 insertions(+), 111 deletions(-)

diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index 273b89a685d5..4810379349d3 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -48,6 +48,15 @@ extern phys_addr_t __mips_cm_phys_base(void);
 extern int mips_cm_is64;
 
 /**
+ * mips_cm_error_report - Report CM cache errors
+ */
+#ifdef CONFIG_MIPS_CM
+extern void mips_cm_error_report(void);
+#else
+static inline void mips_cm_error_report(void) {}
+#endif
+
+/**
  * mips_cm_probe - probe for a Coherence Manager
  *
  * Attempt to detect the presence of a Coherence Manager. Returns 0 if a CM
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 37a9885ef0da..20f36cc9161e 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -17,6 +17,125 @@ void __iomem *mips_cm_base;
 void __iomem *mips_cm_l2sync_base;
 int mips_cm_is64;
 
+static char *cm2_tr[8] = {
+	"mem",	"gcr",	"gic",	"mmio",
+	"0x04", "cpc", "0x06", "0x07"
+};
+
+/* CM3 Tag ECC transation type */
+static char *cm3_tr[16] = {
+	[0x0] = "ReqNoData",
+	[0x1] = "0x1",
+	[0x2] = "ReqWData",
+	[0x3] = "0x3",
+	[0x4] = "IReqNoResp",
+	[0x5] = "IReqWResp",
+	[0x6] = "IReqNoRespDat",
+	[0x7] = "IReqWRespDat",
+	[0x8] = "RespNoData",
+	[0x9] = "RespDataFol",
+	[0xa] = "RespWData",
+	[0xb] = "RespDataOnly",
+	[0xc] = "IRespNoData",
+	[0xd] = "IRespDataFol",
+	[0xe] = "IRespWData",
+	[0xf] = "IRespDataOnly"
+};
+
+static char *cm2_cmd[32] = {
+	[0x00] = "0x00",
+	[0x01] = "Legacy Write",
+	[0x02] = "Legacy Read",
+	[0x03] = "0x03",
+	[0x04] = "0x04",
+	[0x05] = "0x05",
+	[0x06] = "0x06",
+	[0x07] = "0x07",
+	[0x08] = "Coherent Read Own",
+	[0x09] = "Coherent Read Share",
+	[0x0a] = "Coherent Read Discard",
+	[0x0b] = "Coherent Ready Share Always",
+	[0x0c] = "Coherent Upgrade",
+	[0x0d] = "Coherent Writeback",
+	[0x0e] = "0x0e",
+	[0x0f] = "0x0f",
+	[0x10] = "Coherent Copyback",
+	[0x11] = "Coherent Copyback Invalidate",
+	[0x12] = "Coherent Invalidate",
+	[0x13] = "Coherent Write Invalidate",
+	[0x14] = "Coherent Completion Sync",
+	[0x15] = "0x15",
+	[0x16] = "0x16",
+	[0x17] = "0x17",
+	[0x18] = "0x18",
+	[0x19] = "0x19",
+	[0x1a] = "0x1a",
+	[0x1b] = "0x1b",
+	[0x1c] = "0x1c",
+	[0x1d] = "0x1d",
+	[0x1e] = "0x1e",
+	[0x1f] = "0x1f"
+};
+
+/* CM3 Tag ECC command type */
+static char *cm3_cmd[16] = {
+	[0x0] = "Legacy Read",
+	[0x1] = "Legacy Write",
+	[0x2] = "Coherent Read Own",
+	[0x3] = "Coherent Read Share",
+	[0x4] = "Coherent Read Discard",
+	[0x5] = "Coherent Evicted",
+	[0x6] = "Coherent Upgrade",
+	[0x7] = "Coherent Upgrade for Store Conditional",
+	[0x8] = "Coherent Writeback",
+	[0x9] = "Coherent Write Invalidate",
+	[0xa] = "0xa",
+	[0xb] = "0xb",
+	[0xc] = "0xc",
+	[0xd] = "0xd",
+	[0xe] = "0xe",
+	[0xf] = "0xf"
+};
+
+/* CM3 Tag ECC command group */
+static char *cm3_cmd_group[8] = {
+	[0x0] = "Normal",
+	[0x1] = "Registers",
+	[0x2] = "TLB",
+	[0x3] = "0x3",
+	[0x4] = "L1I",
+	[0x5] = "L1D",
+	[0x6] = "L3",
+	[0x7] = "L2"
+};
+
+static char *cm2_core[8] = {
+	"Invalid/OK",	"Invalid/Data",
+	"Shared/OK",	"Shared/Data",
+	"Modified/OK",	"Modified/Data",
+	"Exclusive/OK", "Exclusive/Data"
+};
+
+static char *cm2_causes[32] = {
+	"None", "GC_WR_ERR", "GC_RD_ERR", "COH_WR_ERR",
+	"COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07",
+	"0x08", "0x09", "0x0a", "0x0b",
+	"0x0c", "0x0d", "0x0e", "0x0f",
+	"0x10", "0x11", "0x12", "0x13",
+	"0x14", "0x15", "0x16", "INTVN_WR_ERR",
+	"INTVN_RD_ERR", "0x19", "0x1a", "0x1b",
+	"0x1c", "0x1d", "0x1e", "0x1f"
+};
+
+static char *cm3_causes[32] = {
+	"0x0", "MP_CORRECTABLE_ECC_ERR", "MP_REQUEST_DECODE_ERR",
+	"MP_UNCORRECTABLE_ECC_ERR", "MP_PARITY_ERR", "MP_COHERENCE_ERR",
+	"CMBIU_REQUEST_DECODE_ERR", "CMBIU_PARITY_ERR", "CMBIU_AXI_RESP_ERR",
+	"0x9", "RBI_BUS_ERR", "0xb", "0xc", "0xd", "0xe", "0xf", "0x10",
+	"0x11", "0x12", "0x13", "0x14", "0x15", "0x16", "0x17", "0x18",
+	"0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f"
+};
+
 phys_addr_t __mips_cm_phys_base(void)
 {
 	u32 config3 = read_c0_config3();
@@ -130,3 +249,128 @@ int mips_cm_probe(void)
 
 	return 0;
 }
+
+void mips_cm_error_report(void)
+{
+	unsigned long revision = mips_cm_revision();
+	/*
+	 * CM3 has a 64-bit Error cause register with 0:57 containing the error
+	 * info and 63:58 the error type. For old CMs, everything is contained
+	 * in a single 32-bit register (0:26 and 31:27 respectively). Even
+	 * though the cm_error is u64, we will simply ignore the upper word
+	 * for CM2.
+	 */
+	u64 cm_error = read_gcr_error_cause();
+	int cm_error_cause_sft = CM_GCR_ERROR_CAUSE_ERRTYPE_SHF +
+				 ((revision >= CM_REV_CM3) ? 31 : 0);
+	unsigned long cm_addr = read_gcr_error_addr();
+	unsigned long cm_other = read_gcr_error_mult();
+	int ocause, cause;
+	char buf[256];
+
+	if (!mips_cm_present())
+		return;
+
+	cause = cm_error >> cm_error_cause_sft;
+
+	if (!cause)
+		/* All good */
+		return;
+
+	ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
+	if (revision < CM_REV_CM3) { /* CM2 */
+		if (cause < 16) {
+			unsigned long cca_bits = (cm_error >> 15) & 7;
+			unsigned long tr_bits = (cm_error >> 12) & 7;
+			unsigned long cmd_bits = (cm_error >> 7) & 0x1f;
+			unsigned long stag_bits = (cm_error >> 3) & 15;
+			unsigned long sport_bits = (cm_error >> 0) & 7;
+
+			snprintf(buf, sizeof(buf),
+				 "CCA=%lu TR=%s MCmd=%s STag=%lu "
+				 "SPort=%lu\n", cca_bits, cm2_tr[tr_bits],
+				 cm2_cmd[cmd_bits], stag_bits, sport_bits);
+		} else {
+			/* glob state & sresp together */
+			unsigned long c3_bits = (cm_error >> 18) & 7;
+			unsigned long c2_bits = (cm_error >> 15) & 7;
+			unsigned long c1_bits = (cm_error >> 12) & 7;
+			unsigned long c0_bits = (cm_error >> 9) & 7;
+			unsigned long sc_bit = (cm_error >> 8) & 1;
+			unsigned long cmd_bits = (cm_error >> 3) & 0x1f;
+			unsigned long sport_bits = (cm_error >> 0) & 7;
+
+			snprintf(buf, sizeof(buf),
+				 "C3=%s C2=%s C1=%s C0=%s SC=%s "
+				 "MCmd=%s SPort=%lu\n",
+				 cm2_core[c3_bits], cm2_core[c2_bits],
+				 cm2_core[c1_bits], cm2_core[c0_bits],
+				 sc_bit ? "True" : "False",
+				 cm2_cmd[cmd_bits], sport_bits);
+		}
+			pr_err("CM_ERROR=%08llx %s <%s>\n", cm_error,
+			       cm2_causes[cause], buf);
+		pr_err("CM_ADDR =%08lx\n", cm_addr);
+		pr_err("CM_OTHER=%08lx %s\n", cm_other, cm2_causes[ocause]);
+	} else { /* CM3 */
+	/* Used by cause == {1,2,3} */
+		unsigned long core_id_bits = (cm_error >> 22) & 0xf;
+		unsigned long vp_id_bits = (cm_error >> 18) & 0xf;
+		unsigned long cmd_bits = (cm_error >> 14) & 0xf;
+		unsigned long cmd_group_bits = (cm_error >> 11) & 0xf;
+		unsigned long cm3_cca_bits = (cm_error >> 8) & 7;
+		unsigned long mcp_bits = (cm_error >> 5) & 0xf;
+		unsigned long cm3_tr_bits = (cm_error >> 1) & 0xf;
+		unsigned long sched_bit = cm_error & 0x1;
+
+		if (cause == 1 || cause == 3) { /* Tag ECC */
+			unsigned long tag_ecc = (cm_error >> 57) & 0x1;
+			unsigned long tag_way_bits = (cm_error >> 29) & 0xffff;
+			unsigned long dword_bits = (cm_error >> 49) & 0xff;
+			unsigned long data_way_bits = (cm_error >> 45) & 0xf;
+			unsigned long data_sets_bits = (cm_error >> 29) & 0xfff;
+			unsigned long bank_bit = (cm_error >> 28) & 0x1;
+			snprintf(buf, sizeof(buf),
+				 "%s ECC Error: Way=%lu (DWORD=%lu, Sets=%lu)"
+				 "Bank=%lu CoreID=%lu VPID=%lu Command=%s"
+				 "Command Group=%s CCA=%lu MCP=%d"
+				 "Transaction type=%s Scheduler=%lu\n",
+				 tag_ecc ? "TAG" : "DATA",
+				 tag_ecc ? (unsigned long)ffs(tag_way_bits) - 1 :
+				 data_way_bits, bank_bit, dword_bits,
+				 data_sets_bits,
+				 core_id_bits, vp_id_bits,
+				 cm3_cmd[cmd_bits],
+				 cm3_cmd_group[cmd_group_bits],
+				 cm3_cca_bits, 1 << mcp_bits,
+				 cm3_tr[cm3_tr_bits], sched_bit);
+		} else if (cause == 2) {
+			unsigned long data_error_type = (cm_error >> 41) & 0xfff;
+			unsigned long data_decode_cmd = (cm_error >> 37) & 0xf;
+			unsigned long data_decode_group = (cm_error >> 34) & 0x7;
+			unsigned long data_decode_destination_id = (cm_error >> 28) & 0x3f;
+
+			snprintf(buf, sizeof(buf),
+				 "Decode Request Error: Type=%lu, Command=%lu"
+				 "Command Group=%lu Destination ID=%lu"
+				 "CoreID=%lu VPID=%lu Command=%s"
+				 "Command Group=%s CCA=%lu MCP=%d"
+				 "Transaction type=%s Scheduler=%lu\n",
+				 data_error_type, data_decode_cmd,
+				 data_decode_group, data_decode_destination_id,
+				 core_id_bits, vp_id_bits,
+				 cm3_cmd[cmd_bits],
+				 cm3_cmd_group[cmd_group_bits],
+				 cm3_cca_bits, 1 << mcp_bits,
+				 cm3_tr[cm3_tr_bits], sched_bit);
+		}
+
+		pr_err("CM_ERROR=%llx %s <%s>\n", cm_error,
+		       cm3_causes[cause], buf);
+		pr_err("CM_ADDR =%lx\n", cm_addr);
+		pr_err("CM_OTHER=%lx %s\n", cm_other, cm3_causes[ocause]);
+	}
+
+	/* reprime cause register */
+	write_gcr_error_cause(0);
+}
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index d1392f8f5811..f05aa841f8fb 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -382,122 +382,12 @@ void malta_be_init(void)
 	/* Could change CM error mask register. */
 }
 
-
-static char *tr[8] = {
-	"mem",	"gcr",	"gic",	"mmio",
-	"0x04", "0x05", "0x06", "0x07"
-};
-
-static char *mcmd[32] = {
-	[0x00] = "0x00",
-	[0x01] = "Legacy Write",
-	[0x02] = "Legacy Read",
-	[0x03] = "0x03",
-	[0x04] = "0x04",
-	[0x05] = "0x05",
-	[0x06] = "0x06",
-	[0x07] = "0x07",
-	[0x08] = "Coherent Read Own",
-	[0x09] = "Coherent Read Share",
-	[0x0a] = "Coherent Read Discard",
-	[0x0b] = "Coherent Ready Share Always",
-	[0x0c] = "Coherent Upgrade",
-	[0x0d] = "Coherent Writeback",
-	[0x0e] = "0x0e",
-	[0x0f] = "0x0f",
-	[0x10] = "Coherent Copyback",
-	[0x11] = "Coherent Copyback Invalidate",
-	[0x12] = "Coherent Invalidate",
-	[0x13] = "Coherent Write Invalidate",
-	[0x14] = "Coherent Completion Sync",
-	[0x15] = "0x15",
-	[0x16] = "0x16",
-	[0x17] = "0x17",
-	[0x18] = "0x18",
-	[0x19] = "0x19",
-	[0x1a] = "0x1a",
-	[0x1b] = "0x1b",
-	[0x1c] = "0x1c",
-	[0x1d] = "0x1d",
-	[0x1e] = "0x1e",
-	[0x1f] = "0x1f"
-};
-
-static char *core[8] = {
-	"Invalid/OK",	"Invalid/Data",
-	"Shared/OK",	"Shared/Data",
-	"Modified/OK",	"Modified/Data",
-	"Exclusive/OK", "Exclusive/Data"
-};
-
-static char *causes[32] = {
-	"None", "GC_WR_ERR", "GC_RD_ERR", "COH_WR_ERR",
-	"COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07",
-	"0x08", "0x09", "0x0a", "0x0b",
-	"0x0c", "0x0d", "0x0e", "0x0f",
-	"0x10", "0x11", "0x12", "0x13",
-	"0x14", "0x15", "0x16", "INTVN_WR_ERR",
-	"INTVN_RD_ERR", "0x19", "0x1a", "0x1b",
-	"0x1c", "0x1d", "0x1e", "0x1f"
-};
-
 int malta_be_handler(struct pt_regs *regs, int is_fixup)
 {
 	/* This duplicates the handling in do_be which seems wrong */
 	int retval = is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
 
-	if (mips_cm_present()) {
-		unsigned long cm_error = read_gcr_error_cause();
-		unsigned long cm_addr = read_gcr_error_addr();
-		unsigned long cm_other = read_gcr_error_mult();
-		unsigned long cause, ocause;
-		char buf[256];
-
-		cause = cm_error & CM_GCR_ERROR_CAUSE_ERRTYPE_MSK;
-		if (cause != 0) {
-			cause >>= CM_GCR_ERROR_CAUSE_ERRTYPE_SHF;
-			if (cause < 16) {
-				unsigned long cca_bits = (cm_error >> 15) & 7;
-				unsigned long tr_bits = (cm_error >> 12) & 7;
-				unsigned long cmd_bits = (cm_error >> 7) & 0x1f;
-				unsigned long stag_bits = (cm_error >> 3) & 15;
-				unsigned long sport_bits = (cm_error >> 0) & 7;
-
-				snprintf(buf, sizeof(buf),
-					 "CCA=%lu TR=%s MCmd=%s STag=%lu "
-					 "SPort=%lu\n",
-					 cca_bits, tr[tr_bits], mcmd[cmd_bits],
-					 stag_bits, sport_bits);
-			} else {
-				/* glob state & sresp together */
-				unsigned long c3_bits = (cm_error >> 18) & 7;
-				unsigned long c2_bits = (cm_error >> 15) & 7;
-				unsigned long c1_bits = (cm_error >> 12) & 7;
-				unsigned long c0_bits = (cm_error >> 9) & 7;
-				unsigned long sc_bit = (cm_error >> 8) & 1;
-				unsigned long cmd_bits = (cm_error >> 3) & 0x1f;
-				unsigned long sport_bits = (cm_error >> 0) & 7;
-				snprintf(buf, sizeof(buf),
-					 "C3=%s C2=%s C1=%s C0=%s SC=%s "
-					 "MCmd=%s SPort=%lu\n",
-					 core[c3_bits], core[c2_bits],
-					 core[c1_bits], core[c0_bits],
-					 sc_bit ? "True" : "False",
-					 mcmd[cmd_bits], sport_bits);
-			}
-
-			ocause = (cm_other & CM_GCR_ERROR_MULT_ERR2ND_MSK) >>
-				 CM_GCR_ERROR_MULT_ERR2ND_SHF;
-
-			pr_err("CM_ERROR=%08lx %s <%s>\n", cm_error,
-			       causes[cause], buf);
-			pr_err("CM_ADDR =%08lx\n", cm_addr);
-			pr_err("CM_OTHER=%08lx %s\n", cm_other, causes[ocause]);
-
-			/* reprime cause register */
-			write_gcr_error_cause(0);
-		}
-	}
+	mips_cm_error_report();
 
 	return retval;
 }
-- 
2.4.5

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

* [PATCH 13/19] MIPS: kernel: mips-cm: Add support for reporting CM cache errors
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

The CM cache error reporting code is not Malta specific and as such it
should live in the mips-cm.c file. Moreover, CM2 and CM3 differ in the
way cache errors are being recorded to the registers so extend the
previous code to add support for the CM3 as well.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/mips-cm.h |   9 ++
 arch/mips/kernel/mips-cm.c      | 244 ++++++++++++++++++++++++++++++++++++++++
 arch/mips/mti-malta/malta-int.c | 112 +-----------------
 3 files changed, 254 insertions(+), 111 deletions(-)

diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index 273b89a685d5..4810379349d3 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -48,6 +48,15 @@ extern phys_addr_t __mips_cm_phys_base(void);
 extern int mips_cm_is64;
 
 /**
+ * mips_cm_error_report - Report CM cache errors
+ */
+#ifdef CONFIG_MIPS_CM
+extern void mips_cm_error_report(void);
+#else
+static inline void mips_cm_error_report(void) {}
+#endif
+
+/**
  * mips_cm_probe - probe for a Coherence Manager
  *
  * Attempt to detect the presence of a Coherence Manager. Returns 0 if a CM
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 37a9885ef0da..20f36cc9161e 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -17,6 +17,125 @@ void __iomem *mips_cm_base;
 void __iomem *mips_cm_l2sync_base;
 int mips_cm_is64;
 
+static char *cm2_tr[8] = {
+	"mem",	"gcr",	"gic",	"mmio",
+	"0x04", "cpc", "0x06", "0x07"
+};
+
+/* CM3 Tag ECC transation type */
+static char *cm3_tr[16] = {
+	[0x0] = "ReqNoData",
+	[0x1] = "0x1",
+	[0x2] = "ReqWData",
+	[0x3] = "0x3",
+	[0x4] = "IReqNoResp",
+	[0x5] = "IReqWResp",
+	[0x6] = "IReqNoRespDat",
+	[0x7] = "IReqWRespDat",
+	[0x8] = "RespNoData",
+	[0x9] = "RespDataFol",
+	[0xa] = "RespWData",
+	[0xb] = "RespDataOnly",
+	[0xc] = "IRespNoData",
+	[0xd] = "IRespDataFol",
+	[0xe] = "IRespWData",
+	[0xf] = "IRespDataOnly"
+};
+
+static char *cm2_cmd[32] = {
+	[0x00] = "0x00",
+	[0x01] = "Legacy Write",
+	[0x02] = "Legacy Read",
+	[0x03] = "0x03",
+	[0x04] = "0x04",
+	[0x05] = "0x05",
+	[0x06] = "0x06",
+	[0x07] = "0x07",
+	[0x08] = "Coherent Read Own",
+	[0x09] = "Coherent Read Share",
+	[0x0a] = "Coherent Read Discard",
+	[0x0b] = "Coherent Ready Share Always",
+	[0x0c] = "Coherent Upgrade",
+	[0x0d] = "Coherent Writeback",
+	[0x0e] = "0x0e",
+	[0x0f] = "0x0f",
+	[0x10] = "Coherent Copyback",
+	[0x11] = "Coherent Copyback Invalidate",
+	[0x12] = "Coherent Invalidate",
+	[0x13] = "Coherent Write Invalidate",
+	[0x14] = "Coherent Completion Sync",
+	[0x15] = "0x15",
+	[0x16] = "0x16",
+	[0x17] = "0x17",
+	[0x18] = "0x18",
+	[0x19] = "0x19",
+	[0x1a] = "0x1a",
+	[0x1b] = "0x1b",
+	[0x1c] = "0x1c",
+	[0x1d] = "0x1d",
+	[0x1e] = "0x1e",
+	[0x1f] = "0x1f"
+};
+
+/* CM3 Tag ECC command type */
+static char *cm3_cmd[16] = {
+	[0x0] = "Legacy Read",
+	[0x1] = "Legacy Write",
+	[0x2] = "Coherent Read Own",
+	[0x3] = "Coherent Read Share",
+	[0x4] = "Coherent Read Discard",
+	[0x5] = "Coherent Evicted",
+	[0x6] = "Coherent Upgrade",
+	[0x7] = "Coherent Upgrade for Store Conditional",
+	[0x8] = "Coherent Writeback",
+	[0x9] = "Coherent Write Invalidate",
+	[0xa] = "0xa",
+	[0xb] = "0xb",
+	[0xc] = "0xc",
+	[0xd] = "0xd",
+	[0xe] = "0xe",
+	[0xf] = "0xf"
+};
+
+/* CM3 Tag ECC command group */
+static char *cm3_cmd_group[8] = {
+	[0x0] = "Normal",
+	[0x1] = "Registers",
+	[0x2] = "TLB",
+	[0x3] = "0x3",
+	[0x4] = "L1I",
+	[0x5] = "L1D",
+	[0x6] = "L3",
+	[0x7] = "L2"
+};
+
+static char *cm2_core[8] = {
+	"Invalid/OK",	"Invalid/Data",
+	"Shared/OK",	"Shared/Data",
+	"Modified/OK",	"Modified/Data",
+	"Exclusive/OK", "Exclusive/Data"
+};
+
+static char *cm2_causes[32] = {
+	"None", "GC_WR_ERR", "GC_RD_ERR", "COH_WR_ERR",
+	"COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07",
+	"0x08", "0x09", "0x0a", "0x0b",
+	"0x0c", "0x0d", "0x0e", "0x0f",
+	"0x10", "0x11", "0x12", "0x13",
+	"0x14", "0x15", "0x16", "INTVN_WR_ERR",
+	"INTVN_RD_ERR", "0x19", "0x1a", "0x1b",
+	"0x1c", "0x1d", "0x1e", "0x1f"
+};
+
+static char *cm3_causes[32] = {
+	"0x0", "MP_CORRECTABLE_ECC_ERR", "MP_REQUEST_DECODE_ERR",
+	"MP_UNCORRECTABLE_ECC_ERR", "MP_PARITY_ERR", "MP_COHERENCE_ERR",
+	"CMBIU_REQUEST_DECODE_ERR", "CMBIU_PARITY_ERR", "CMBIU_AXI_RESP_ERR",
+	"0x9", "RBI_BUS_ERR", "0xb", "0xc", "0xd", "0xe", "0xf", "0x10",
+	"0x11", "0x12", "0x13", "0x14", "0x15", "0x16", "0x17", "0x18",
+	"0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f"
+};
+
 phys_addr_t __mips_cm_phys_base(void)
 {
 	u32 config3 = read_c0_config3();
@@ -130,3 +249,128 @@ int mips_cm_probe(void)
 
 	return 0;
 }
+
+void mips_cm_error_report(void)
+{
+	unsigned long revision = mips_cm_revision();
+	/*
+	 * CM3 has a 64-bit Error cause register with 0:57 containing the error
+	 * info and 63:58 the error type. For old CMs, everything is contained
+	 * in a single 32-bit register (0:26 and 31:27 respectively). Even
+	 * though the cm_error is u64, we will simply ignore the upper word
+	 * for CM2.
+	 */
+	u64 cm_error = read_gcr_error_cause();
+	int cm_error_cause_sft = CM_GCR_ERROR_CAUSE_ERRTYPE_SHF +
+				 ((revision >= CM_REV_CM3) ? 31 : 0);
+	unsigned long cm_addr = read_gcr_error_addr();
+	unsigned long cm_other = read_gcr_error_mult();
+	int ocause, cause;
+	char buf[256];
+
+	if (!mips_cm_present())
+		return;
+
+	cause = cm_error >> cm_error_cause_sft;
+
+	if (!cause)
+		/* All good */
+		return;
+
+	ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
+	if (revision < CM_REV_CM3) { /* CM2 */
+		if (cause < 16) {
+			unsigned long cca_bits = (cm_error >> 15) & 7;
+			unsigned long tr_bits = (cm_error >> 12) & 7;
+			unsigned long cmd_bits = (cm_error >> 7) & 0x1f;
+			unsigned long stag_bits = (cm_error >> 3) & 15;
+			unsigned long sport_bits = (cm_error >> 0) & 7;
+
+			snprintf(buf, sizeof(buf),
+				 "CCA=%lu TR=%s MCmd=%s STag=%lu "
+				 "SPort=%lu\n", cca_bits, cm2_tr[tr_bits],
+				 cm2_cmd[cmd_bits], stag_bits, sport_bits);
+		} else {
+			/* glob state & sresp together */
+			unsigned long c3_bits = (cm_error >> 18) & 7;
+			unsigned long c2_bits = (cm_error >> 15) & 7;
+			unsigned long c1_bits = (cm_error >> 12) & 7;
+			unsigned long c0_bits = (cm_error >> 9) & 7;
+			unsigned long sc_bit = (cm_error >> 8) & 1;
+			unsigned long cmd_bits = (cm_error >> 3) & 0x1f;
+			unsigned long sport_bits = (cm_error >> 0) & 7;
+
+			snprintf(buf, sizeof(buf),
+				 "C3=%s C2=%s C1=%s C0=%s SC=%s "
+				 "MCmd=%s SPort=%lu\n",
+				 cm2_core[c3_bits], cm2_core[c2_bits],
+				 cm2_core[c1_bits], cm2_core[c0_bits],
+				 sc_bit ? "True" : "False",
+				 cm2_cmd[cmd_bits], sport_bits);
+		}
+			pr_err("CM_ERROR=%08llx %s <%s>\n", cm_error,
+			       cm2_causes[cause], buf);
+		pr_err("CM_ADDR =%08lx\n", cm_addr);
+		pr_err("CM_OTHER=%08lx %s\n", cm_other, cm2_causes[ocause]);
+	} else { /* CM3 */
+	/* Used by cause == {1,2,3} */
+		unsigned long core_id_bits = (cm_error >> 22) & 0xf;
+		unsigned long vp_id_bits = (cm_error >> 18) & 0xf;
+		unsigned long cmd_bits = (cm_error >> 14) & 0xf;
+		unsigned long cmd_group_bits = (cm_error >> 11) & 0xf;
+		unsigned long cm3_cca_bits = (cm_error >> 8) & 7;
+		unsigned long mcp_bits = (cm_error >> 5) & 0xf;
+		unsigned long cm3_tr_bits = (cm_error >> 1) & 0xf;
+		unsigned long sched_bit = cm_error & 0x1;
+
+		if (cause == 1 || cause == 3) { /* Tag ECC */
+			unsigned long tag_ecc = (cm_error >> 57) & 0x1;
+			unsigned long tag_way_bits = (cm_error >> 29) & 0xffff;
+			unsigned long dword_bits = (cm_error >> 49) & 0xff;
+			unsigned long data_way_bits = (cm_error >> 45) & 0xf;
+			unsigned long data_sets_bits = (cm_error >> 29) & 0xfff;
+			unsigned long bank_bit = (cm_error >> 28) & 0x1;
+			snprintf(buf, sizeof(buf),
+				 "%s ECC Error: Way=%lu (DWORD=%lu, Sets=%lu)"
+				 "Bank=%lu CoreID=%lu VPID=%lu Command=%s"
+				 "Command Group=%s CCA=%lu MCP=%d"
+				 "Transaction type=%s Scheduler=%lu\n",
+				 tag_ecc ? "TAG" : "DATA",
+				 tag_ecc ? (unsigned long)ffs(tag_way_bits) - 1 :
+				 data_way_bits, bank_bit, dword_bits,
+				 data_sets_bits,
+				 core_id_bits, vp_id_bits,
+				 cm3_cmd[cmd_bits],
+				 cm3_cmd_group[cmd_group_bits],
+				 cm3_cca_bits, 1 << mcp_bits,
+				 cm3_tr[cm3_tr_bits], sched_bit);
+		} else if (cause == 2) {
+			unsigned long data_error_type = (cm_error >> 41) & 0xfff;
+			unsigned long data_decode_cmd = (cm_error >> 37) & 0xf;
+			unsigned long data_decode_group = (cm_error >> 34) & 0x7;
+			unsigned long data_decode_destination_id = (cm_error >> 28) & 0x3f;
+
+			snprintf(buf, sizeof(buf),
+				 "Decode Request Error: Type=%lu, Command=%lu"
+				 "Command Group=%lu Destination ID=%lu"
+				 "CoreID=%lu VPID=%lu Command=%s"
+				 "Command Group=%s CCA=%lu MCP=%d"
+				 "Transaction type=%s Scheduler=%lu\n",
+				 data_error_type, data_decode_cmd,
+				 data_decode_group, data_decode_destination_id,
+				 core_id_bits, vp_id_bits,
+				 cm3_cmd[cmd_bits],
+				 cm3_cmd_group[cmd_group_bits],
+				 cm3_cca_bits, 1 << mcp_bits,
+				 cm3_tr[cm3_tr_bits], sched_bit);
+		}
+
+		pr_err("CM_ERROR=%llx %s <%s>\n", cm_error,
+		       cm3_causes[cause], buf);
+		pr_err("CM_ADDR =%lx\n", cm_addr);
+		pr_err("CM_OTHER=%lx %s\n", cm_other, cm3_causes[ocause]);
+	}
+
+	/* reprime cause register */
+	write_gcr_error_cause(0);
+}
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index d1392f8f5811..f05aa841f8fb 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -382,122 +382,12 @@ void malta_be_init(void)
 	/* Could change CM error mask register. */
 }
 
-
-static char *tr[8] = {
-	"mem",	"gcr",	"gic",	"mmio",
-	"0x04", "0x05", "0x06", "0x07"
-};
-
-static char *mcmd[32] = {
-	[0x00] = "0x00",
-	[0x01] = "Legacy Write",
-	[0x02] = "Legacy Read",
-	[0x03] = "0x03",
-	[0x04] = "0x04",
-	[0x05] = "0x05",
-	[0x06] = "0x06",
-	[0x07] = "0x07",
-	[0x08] = "Coherent Read Own",
-	[0x09] = "Coherent Read Share",
-	[0x0a] = "Coherent Read Discard",
-	[0x0b] = "Coherent Ready Share Always",
-	[0x0c] = "Coherent Upgrade",
-	[0x0d] = "Coherent Writeback",
-	[0x0e] = "0x0e",
-	[0x0f] = "0x0f",
-	[0x10] = "Coherent Copyback",
-	[0x11] = "Coherent Copyback Invalidate",
-	[0x12] = "Coherent Invalidate",
-	[0x13] = "Coherent Write Invalidate",
-	[0x14] = "Coherent Completion Sync",
-	[0x15] = "0x15",
-	[0x16] = "0x16",
-	[0x17] = "0x17",
-	[0x18] = "0x18",
-	[0x19] = "0x19",
-	[0x1a] = "0x1a",
-	[0x1b] = "0x1b",
-	[0x1c] = "0x1c",
-	[0x1d] = "0x1d",
-	[0x1e] = "0x1e",
-	[0x1f] = "0x1f"
-};
-
-static char *core[8] = {
-	"Invalid/OK",	"Invalid/Data",
-	"Shared/OK",	"Shared/Data",
-	"Modified/OK",	"Modified/Data",
-	"Exclusive/OK", "Exclusive/Data"
-};
-
-static char *causes[32] = {
-	"None", "GC_WR_ERR", "GC_RD_ERR", "COH_WR_ERR",
-	"COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07",
-	"0x08", "0x09", "0x0a", "0x0b",
-	"0x0c", "0x0d", "0x0e", "0x0f",
-	"0x10", "0x11", "0x12", "0x13",
-	"0x14", "0x15", "0x16", "INTVN_WR_ERR",
-	"INTVN_RD_ERR", "0x19", "0x1a", "0x1b",
-	"0x1c", "0x1d", "0x1e", "0x1f"
-};
-
 int malta_be_handler(struct pt_regs *regs, int is_fixup)
 {
 	/* This duplicates the handling in do_be which seems wrong */
 	int retval = is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
 
-	if (mips_cm_present()) {
-		unsigned long cm_error = read_gcr_error_cause();
-		unsigned long cm_addr = read_gcr_error_addr();
-		unsigned long cm_other = read_gcr_error_mult();
-		unsigned long cause, ocause;
-		char buf[256];
-
-		cause = cm_error & CM_GCR_ERROR_CAUSE_ERRTYPE_MSK;
-		if (cause != 0) {
-			cause >>= CM_GCR_ERROR_CAUSE_ERRTYPE_SHF;
-			if (cause < 16) {
-				unsigned long cca_bits = (cm_error >> 15) & 7;
-				unsigned long tr_bits = (cm_error >> 12) & 7;
-				unsigned long cmd_bits = (cm_error >> 7) & 0x1f;
-				unsigned long stag_bits = (cm_error >> 3) & 15;
-				unsigned long sport_bits = (cm_error >> 0) & 7;
-
-				snprintf(buf, sizeof(buf),
-					 "CCA=%lu TR=%s MCmd=%s STag=%lu "
-					 "SPort=%lu\n",
-					 cca_bits, tr[tr_bits], mcmd[cmd_bits],
-					 stag_bits, sport_bits);
-			} else {
-				/* glob state & sresp together */
-				unsigned long c3_bits = (cm_error >> 18) & 7;
-				unsigned long c2_bits = (cm_error >> 15) & 7;
-				unsigned long c1_bits = (cm_error >> 12) & 7;
-				unsigned long c0_bits = (cm_error >> 9) & 7;
-				unsigned long sc_bit = (cm_error >> 8) & 1;
-				unsigned long cmd_bits = (cm_error >> 3) & 0x1f;
-				unsigned long sport_bits = (cm_error >> 0) & 7;
-				snprintf(buf, sizeof(buf),
-					 "C3=%s C2=%s C1=%s C0=%s SC=%s "
-					 "MCmd=%s SPort=%lu\n",
-					 core[c3_bits], core[c2_bits],
-					 core[c1_bits], core[c0_bits],
-					 sc_bit ? "True" : "False",
-					 mcmd[cmd_bits], sport_bits);
-			}
-
-			ocause = (cm_other & CM_GCR_ERROR_MULT_ERR2ND_MSK) >>
-				 CM_GCR_ERROR_MULT_ERR2ND_SHF;
-
-			pr_err("CM_ERROR=%08lx %s <%s>\n", cm_error,
-			       causes[cause], buf);
-			pr_err("CM_ADDR =%08lx\n", cm_addr);
-			pr_err("CM_OTHER=%08lx %s\n", cm_other, causes[ocause]);
-
-			/* reprime cause register */
-			write_gcr_error_cause(0);
-		}
-	}
+	mips_cm_error_report();
 
 	return retval;
 }
-- 
2.4.5

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

* [PATCH 14/19] drivers: irqchip: irq-mips-gic: Extend GIC accessors for 64-bit CMs
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips
  Cc: Markos Chandras, Thomas Gleixner, Jason Cooper, Andrew Bresticker,
	Paul Burton

Previously, the GIC accessors were only accessing u32 registers but
newer CMs may actually be 64-bit on MIPS64 cores. As a result of which,
extended these accessors to support 64-bit reads and writes.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Bresticker <abrestic@chromium.org>
Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 drivers/irqchip/irq-mips-gic.c   | 119 ++++++++++++++++++++++++---------------
 include/linux/irqchip/mips-gic.h |  10 +++-
 2 files changed, 83 insertions(+), 46 deletions(-)

diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 4400edd1a6c7..29c494691b71 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -42,20 +42,46 @@ static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller;
 
 static void __gic_irq_dispatch(void);
 
-static inline unsigned int gic_read(unsigned int reg)
+static inline u32 gic_read32(unsigned int reg)
 {
 	return __raw_readl(gic_base + reg);
 }
 
-static inline void gic_write(unsigned int reg, unsigned int val)
+static inline u64 gic_read64(unsigned int reg)
 {
-	__raw_writel(val, gic_base + reg);
+	return __raw_readq(gic_base + reg);
 }
 
-static inline void gic_update_bits(unsigned int reg, unsigned int mask,
-				   unsigned int val)
+static inline unsigned long gic_read(unsigned int reg)
 {
-	unsigned int regval;
+	if (!mips_cm_is64)
+		return gic_read32(reg);
+	else
+		return gic_read64(reg);
+}
+
+static inline void gic_write32(unsigned int reg, u32 val)
+{
+	return __raw_writel(val, gic_base + reg);
+}
+
+static inline void gic_write64(unsigned int reg, u64 val)
+{
+	return __raw_writeq(val, gic_base + reg);
+}
+
+static inline void gic_write(unsigned int reg, unsigned long val)
+{
+	if (!mips_cm_is64)
+		return gic_write32(reg, (u32)val);
+	else
+		return gic_write64(reg, (u64)val);
+}
+
+static inline void gic_update_bits(unsigned int reg, unsigned long mask,
+				   unsigned long val)
+{
+	unsigned long regval;
 
 	regval = gic_read(reg);
 	regval &= ~mask;
@@ -66,40 +92,40 @@ static inline void gic_update_bits(unsigned int reg, unsigned int mask,
 static inline void gic_reset_mask(unsigned int intr)
 {
 	gic_write(GIC_REG(SHARED, GIC_SH_RMASK) + GIC_INTR_OFS(intr),
-		  1 << GIC_INTR_BIT(intr));
+		  1ul << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_mask(unsigned int intr)
 {
 	gic_write(GIC_REG(SHARED, GIC_SH_SMASK) + GIC_INTR_OFS(intr),
-		  1 << GIC_INTR_BIT(intr));
+		  1ul << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_polarity(unsigned int intr, unsigned int pol)
 {
 	gic_update_bits(GIC_REG(SHARED, GIC_SH_SET_POLARITY) +
-			GIC_INTR_OFS(intr), 1 << GIC_INTR_BIT(intr),
-			pol << GIC_INTR_BIT(intr));
+			GIC_INTR_OFS(intr), 1ul << GIC_INTR_BIT(intr),
+			(unsigned long)pol << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_trigger(unsigned int intr, unsigned int trig)
 {
 	gic_update_bits(GIC_REG(SHARED, GIC_SH_SET_TRIGGER) +
-			GIC_INTR_OFS(intr), 1 << GIC_INTR_BIT(intr),
-			trig << GIC_INTR_BIT(intr));
+			GIC_INTR_OFS(intr), 1ul << GIC_INTR_BIT(intr),
+			(unsigned long)trig << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_dual_edge(unsigned int intr, unsigned int dual)
 {
 	gic_update_bits(GIC_REG(SHARED, GIC_SH_SET_DUAL) + GIC_INTR_OFS(intr),
-			1 << GIC_INTR_BIT(intr),
-			dual << GIC_INTR_BIT(intr));
+			1ul << GIC_INTR_BIT(intr),
+			(unsigned long)dual << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_map_to_pin(unsigned int intr, unsigned int pin)
 {
-	gic_write(GIC_REG(SHARED, GIC_SH_INTR_MAP_TO_PIN_BASE) +
-		  GIC_SH_MAP_TO_PIN(intr), GIC_MAP_TO_PIN_MSK | pin);
+	gic_write32(GIC_REG(SHARED, GIC_SH_INTR_MAP_TO_PIN_BASE) +
+		    GIC_SH_MAP_TO_PIN(intr), GIC_MAP_TO_PIN_MSK | pin);
 }
 
 static inline void gic_map_to_vpe(unsigned int intr, unsigned int vpe)
@@ -115,9 +141,9 @@ cycle_t gic_read_count(void)
 	unsigned int hi, hi2, lo;
 
 	do {
-		hi = gic_read(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
-		lo = gic_read(GIC_REG(SHARED, GIC_SH_COUNTER_31_00));
-		hi2 = gic_read(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
+		hi = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
+		lo = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_31_00));
+		hi2 = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
 	} while (hi2 != hi);
 
 	return (((cycle_t) hi) << 32) + lo;
@@ -136,9 +162,9 @@ unsigned int gic_get_count_width(void)
 
 void gic_write_compare(cycle_t cnt)
 {
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
 				(int)(cnt >> 32));
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
 				(int)(cnt & 0xffffffff));
 }
 
@@ -148,10 +174,10 @@ void gic_write_cpu_compare(cycle_t cnt, int cpu)
 
 	local_irq_save(flags);
 
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
-	gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
+	gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
 				(int)(cnt >> 32));
-	gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
+	gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
 				(int)(cnt & 0xffffffff));
 
 	local_irq_restore(flags);
@@ -161,8 +187,8 @@ cycle_t gic_read_compare(void)
 {
 	unsigned int hi, lo;
 
-	hi = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI));
-	lo = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO));
+	hi = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI));
+	lo = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO));
 
 	return (((cycle_t) hi) << 32) + lo;
 }
@@ -197,7 +223,7 @@ static bool gic_local_irq_is_routable(int intr)
 	if (cpu_has_veic)
 		return true;
 
-	vpe_ctl = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_CTL));
+	vpe_ctl = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_CTL));
 	switch (intr) {
 	case GIC_LOCAL_INT_TIMER:
 		return vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK;
@@ -273,7 +299,7 @@ int gic_get_c0_fdc_int(void)
 
 static void gic_handle_shared_int(bool chained)
 {
-	unsigned int i, intr, virq;
+	unsigned int i, intr, virq, gic_reg_step = mips_cm_is64 ? 8 : 4;
 	unsigned long *pcpu_mask;
 	unsigned long pending_reg, intrmask_reg;
 	DECLARE_BITMAP(pending, GIC_MAX_INTRS);
@@ -288,8 +314,8 @@ static void gic_handle_shared_int(bool chained)
 	for (i = 0; i < BITS_TO_LONGS(gic_shared_intrs); i++) {
 		pending[i] = gic_read(pending_reg);
 		intrmask[i] = gic_read(intrmask_reg);
-		pending_reg += 0x4;
-		intrmask_reg += 0x4;
+		pending_reg += gic_reg_step;
+		intrmask_reg += gic_reg_step;
 	}
 
 	bitmap_and(pending, pending, intrmask, gic_shared_intrs);
@@ -439,8 +465,8 @@ static void gic_handle_local_int(bool chained)
 	unsigned long pending, masked;
 	unsigned int intr, virq;
 
-	pending = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_PEND));
-	masked = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_MASK));
+	pending = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_PEND));
+	masked = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_MASK));
 
 	bitmap_and(&pending, &pending, &masked, GIC_NUM_LOCAL_INTRS);
 
@@ -463,14 +489,14 @@ static void gic_mask_local_irq(struct irq_data *d)
 {
 	int intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
 
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_RMASK), 1 << intr);
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_RMASK), 1 << intr);
 }
 
 static void gic_unmask_local_irq(struct irq_data *d)
 {
 	int intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
 
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), 1 << intr);
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), 1 << intr);
 }
 
 static struct irq_chip gic_local_irq_controller = {
@@ -488,7 +514,7 @@ static void gic_mask_local_irq_all_vpes(struct irq_data *d)
 	spin_lock_irqsave(&gic_lock, flags);
 	for (i = 0; i < gic_vpes; i++) {
 		gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
-		gic_write(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << intr);
+		gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << intr);
 	}
 	spin_unlock_irqrestore(&gic_lock, flags);
 }
@@ -502,7 +528,7 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
 	spin_lock_irqsave(&gic_lock, flags);
 	for (i = 0; i < gic_vpes; i++) {
 		gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
-		gic_write(GIC_REG(VPE_OTHER, GIC_VPE_SMASK), 1 << intr);
+		gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SMASK), 1 << intr);
 	}
 	spin_unlock_irqrestore(&gic_lock, flags);
 }
@@ -667,27 +693,32 @@ static int gic_local_irq_domain_map(struct irq_domain *d, unsigned int virq,
 
 		switch (intr) {
 		case GIC_LOCAL_INT_WD:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_WD_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_WD_MAP), val);
 			break;
 		case GIC_LOCAL_INT_COMPARE:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_TIMER:
 			/* CONFIG_MIPS_CMP workaround (see __gic_init) */
 			val = GIC_MAP_TO_PIN_MSK | timer_cpu_pin;
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_PERFCTR:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_SWINT0:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_SWINT0_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SWINT0_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_SWINT1:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_SWINT1_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SWINT1_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_FDC:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_FDC_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_FDC_MAP), val);
 			break;
 		default:
 			pr_err("Invalid local IRQ %d\n", intr);
@@ -792,7 +823,7 @@ static void __init __gic_init(unsigned long gic_base_addr,
 		 */
 		if (IS_ENABLED(CONFIG_MIPS_CMP) &&
 		    gic_local_irq_is_routable(GIC_LOCAL_INT_TIMER)) {
-			timer_cpu_pin = gic_read(GIC_REG(VPE_LOCAL,
+			timer_cpu_pin = gic_read32(GIC_REG(VPE_LOCAL,
 							 GIC_VPE_TIMER_MAP)) &
 					GIC_MAP_MSK;
 			irq_set_chained_handler(MIPS_CPU_IRQ_BASE +
diff --git a/include/linux/irqchip/mips-gic.h b/include/linux/irqchip/mips-gic.h
index 9b1ad3734911..10e4a9073019 100644
--- a/include/linux/irqchip/mips-gic.h
+++ b/include/linux/irqchip/mips-gic.h
@@ -45,8 +45,14 @@
 #define GIC_SH_REVISIONID_OFS		0x0020
 
 /* Convert an interrupt number to a byte offset/bit for multi-word registers */
-#define GIC_INTR_OFS(intr)		(((intr) / 32) * 4)
-#define GIC_INTR_BIT(intr)		((intr) % 32)
+#define GIC_INTR_OFS(intr) ({				\
+	unsigned bits = mips_cm_is64 ? 64 : 32;		\
+	unsigned reg_idx = (intr) / bits;		\
+	unsigned reg_width = bits / 8;			\
+							\
+	reg_idx * reg_width;				\
+})
+#define GIC_INTR_BIT(intr)		((intr) % (mips_cm_is64 ? 64 : 32))
 
 /* Polarity : Reset Value is always 0 */
 #define GIC_SH_SET_POLARITY_OFS		0x0100
-- 
2.4.5

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

* [PATCH 14/19] drivers: irqchip: irq-mips-gic: Extend GIC accessors for 64-bit CMs
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips
  Cc: Markos Chandras, Thomas Gleixner, Jason Cooper, Andrew Bresticker,
	Paul Burton

Previously, the GIC accessors were only accessing u32 registers but
newer CMs may actually be 64-bit on MIPS64 cores. As a result of which,
extended these accessors to support 64-bit reads and writes.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Bresticker <abrestic@chromium.org>
Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 drivers/irqchip/irq-mips-gic.c   | 119 ++++++++++++++++++++++++---------------
 include/linux/irqchip/mips-gic.h |  10 +++-
 2 files changed, 83 insertions(+), 46 deletions(-)

diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 4400edd1a6c7..29c494691b71 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -42,20 +42,46 @@ static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller;
 
 static void __gic_irq_dispatch(void);
 
-static inline unsigned int gic_read(unsigned int reg)
+static inline u32 gic_read32(unsigned int reg)
 {
 	return __raw_readl(gic_base + reg);
 }
 
-static inline void gic_write(unsigned int reg, unsigned int val)
+static inline u64 gic_read64(unsigned int reg)
 {
-	__raw_writel(val, gic_base + reg);
+	return __raw_readq(gic_base + reg);
 }
 
-static inline void gic_update_bits(unsigned int reg, unsigned int mask,
-				   unsigned int val)
+static inline unsigned long gic_read(unsigned int reg)
 {
-	unsigned int regval;
+	if (!mips_cm_is64)
+		return gic_read32(reg);
+	else
+		return gic_read64(reg);
+}
+
+static inline void gic_write32(unsigned int reg, u32 val)
+{
+	return __raw_writel(val, gic_base + reg);
+}
+
+static inline void gic_write64(unsigned int reg, u64 val)
+{
+	return __raw_writeq(val, gic_base + reg);
+}
+
+static inline void gic_write(unsigned int reg, unsigned long val)
+{
+	if (!mips_cm_is64)
+		return gic_write32(reg, (u32)val);
+	else
+		return gic_write64(reg, (u64)val);
+}
+
+static inline void gic_update_bits(unsigned int reg, unsigned long mask,
+				   unsigned long val)
+{
+	unsigned long regval;
 
 	regval = gic_read(reg);
 	regval &= ~mask;
@@ -66,40 +92,40 @@ static inline void gic_update_bits(unsigned int reg, unsigned int mask,
 static inline void gic_reset_mask(unsigned int intr)
 {
 	gic_write(GIC_REG(SHARED, GIC_SH_RMASK) + GIC_INTR_OFS(intr),
-		  1 << GIC_INTR_BIT(intr));
+		  1ul << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_mask(unsigned int intr)
 {
 	gic_write(GIC_REG(SHARED, GIC_SH_SMASK) + GIC_INTR_OFS(intr),
-		  1 << GIC_INTR_BIT(intr));
+		  1ul << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_polarity(unsigned int intr, unsigned int pol)
 {
 	gic_update_bits(GIC_REG(SHARED, GIC_SH_SET_POLARITY) +
-			GIC_INTR_OFS(intr), 1 << GIC_INTR_BIT(intr),
-			pol << GIC_INTR_BIT(intr));
+			GIC_INTR_OFS(intr), 1ul << GIC_INTR_BIT(intr),
+			(unsigned long)pol << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_trigger(unsigned int intr, unsigned int trig)
 {
 	gic_update_bits(GIC_REG(SHARED, GIC_SH_SET_TRIGGER) +
-			GIC_INTR_OFS(intr), 1 << GIC_INTR_BIT(intr),
-			trig << GIC_INTR_BIT(intr));
+			GIC_INTR_OFS(intr), 1ul << GIC_INTR_BIT(intr),
+			(unsigned long)trig << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_dual_edge(unsigned int intr, unsigned int dual)
 {
 	gic_update_bits(GIC_REG(SHARED, GIC_SH_SET_DUAL) + GIC_INTR_OFS(intr),
-			1 << GIC_INTR_BIT(intr),
-			dual << GIC_INTR_BIT(intr));
+			1ul << GIC_INTR_BIT(intr),
+			(unsigned long)dual << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_map_to_pin(unsigned int intr, unsigned int pin)
 {
-	gic_write(GIC_REG(SHARED, GIC_SH_INTR_MAP_TO_PIN_BASE) +
-		  GIC_SH_MAP_TO_PIN(intr), GIC_MAP_TO_PIN_MSK | pin);
+	gic_write32(GIC_REG(SHARED, GIC_SH_INTR_MAP_TO_PIN_BASE) +
+		    GIC_SH_MAP_TO_PIN(intr), GIC_MAP_TO_PIN_MSK | pin);
 }
 
 static inline void gic_map_to_vpe(unsigned int intr, unsigned int vpe)
@@ -115,9 +141,9 @@ cycle_t gic_read_count(void)
 	unsigned int hi, hi2, lo;
 
 	do {
-		hi = gic_read(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
-		lo = gic_read(GIC_REG(SHARED, GIC_SH_COUNTER_31_00));
-		hi2 = gic_read(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
+		hi = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
+		lo = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_31_00));
+		hi2 = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
 	} while (hi2 != hi);
 
 	return (((cycle_t) hi) << 32) + lo;
@@ -136,9 +162,9 @@ unsigned int gic_get_count_width(void)
 
 void gic_write_compare(cycle_t cnt)
 {
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
 				(int)(cnt >> 32));
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
 				(int)(cnt & 0xffffffff));
 }
 
@@ -148,10 +174,10 @@ void gic_write_cpu_compare(cycle_t cnt, int cpu)
 
 	local_irq_save(flags);
 
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
-	gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
+	gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
 				(int)(cnt >> 32));
-	gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
+	gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
 				(int)(cnt & 0xffffffff));
 
 	local_irq_restore(flags);
@@ -161,8 +187,8 @@ cycle_t gic_read_compare(void)
 {
 	unsigned int hi, lo;
 
-	hi = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI));
-	lo = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO));
+	hi = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI));
+	lo = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO));
 
 	return (((cycle_t) hi) << 32) + lo;
 }
@@ -197,7 +223,7 @@ static bool gic_local_irq_is_routable(int intr)
 	if (cpu_has_veic)
 		return true;
 
-	vpe_ctl = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_CTL));
+	vpe_ctl = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_CTL));
 	switch (intr) {
 	case GIC_LOCAL_INT_TIMER:
 		return vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK;
@@ -273,7 +299,7 @@ int gic_get_c0_fdc_int(void)
 
 static void gic_handle_shared_int(bool chained)
 {
-	unsigned int i, intr, virq;
+	unsigned int i, intr, virq, gic_reg_step = mips_cm_is64 ? 8 : 4;
 	unsigned long *pcpu_mask;
 	unsigned long pending_reg, intrmask_reg;
 	DECLARE_BITMAP(pending, GIC_MAX_INTRS);
@@ -288,8 +314,8 @@ static void gic_handle_shared_int(bool chained)
 	for (i = 0; i < BITS_TO_LONGS(gic_shared_intrs); i++) {
 		pending[i] = gic_read(pending_reg);
 		intrmask[i] = gic_read(intrmask_reg);
-		pending_reg += 0x4;
-		intrmask_reg += 0x4;
+		pending_reg += gic_reg_step;
+		intrmask_reg += gic_reg_step;
 	}
 
 	bitmap_and(pending, pending, intrmask, gic_shared_intrs);
@@ -439,8 +465,8 @@ static void gic_handle_local_int(bool chained)
 	unsigned long pending, masked;
 	unsigned int intr, virq;
 
-	pending = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_PEND));
-	masked = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_MASK));
+	pending = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_PEND));
+	masked = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_MASK));
 
 	bitmap_and(&pending, &pending, &masked, GIC_NUM_LOCAL_INTRS);
 
@@ -463,14 +489,14 @@ static void gic_mask_local_irq(struct irq_data *d)
 {
 	int intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
 
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_RMASK), 1 << intr);
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_RMASK), 1 << intr);
 }
 
 static void gic_unmask_local_irq(struct irq_data *d)
 {
 	int intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
 
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), 1 << intr);
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), 1 << intr);
 }
 
 static struct irq_chip gic_local_irq_controller = {
@@ -488,7 +514,7 @@ static void gic_mask_local_irq_all_vpes(struct irq_data *d)
 	spin_lock_irqsave(&gic_lock, flags);
 	for (i = 0; i < gic_vpes; i++) {
 		gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
-		gic_write(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << intr);
+		gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << intr);
 	}
 	spin_unlock_irqrestore(&gic_lock, flags);
 }
@@ -502,7 +528,7 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
 	spin_lock_irqsave(&gic_lock, flags);
 	for (i = 0; i < gic_vpes; i++) {
 		gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
-		gic_write(GIC_REG(VPE_OTHER, GIC_VPE_SMASK), 1 << intr);
+		gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SMASK), 1 << intr);
 	}
 	spin_unlock_irqrestore(&gic_lock, flags);
 }
@@ -667,27 +693,32 @@ static int gic_local_irq_domain_map(struct irq_domain *d, unsigned int virq,
 
 		switch (intr) {
 		case GIC_LOCAL_INT_WD:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_WD_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_WD_MAP), val);
 			break;
 		case GIC_LOCAL_INT_COMPARE:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_TIMER:
 			/* CONFIG_MIPS_CMP workaround (see __gic_init) */
 			val = GIC_MAP_TO_PIN_MSK | timer_cpu_pin;
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_PERFCTR:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_SWINT0:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_SWINT0_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SWINT0_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_SWINT1:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_SWINT1_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SWINT1_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_FDC:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_FDC_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_FDC_MAP), val);
 			break;
 		default:
 			pr_err("Invalid local IRQ %d\n", intr);
@@ -792,7 +823,7 @@ static void __init __gic_init(unsigned long gic_base_addr,
 		 */
 		if (IS_ENABLED(CONFIG_MIPS_CMP) &&
 		    gic_local_irq_is_routable(GIC_LOCAL_INT_TIMER)) {
-			timer_cpu_pin = gic_read(GIC_REG(VPE_LOCAL,
+			timer_cpu_pin = gic_read32(GIC_REG(VPE_LOCAL,
 							 GIC_VPE_TIMER_MAP)) &
 					GIC_MAP_MSK;
 			irq_set_chained_handler(MIPS_CPU_IRQ_BASE +
diff --git a/include/linux/irqchip/mips-gic.h b/include/linux/irqchip/mips-gic.h
index 9b1ad3734911..10e4a9073019 100644
--- a/include/linux/irqchip/mips-gic.h
+++ b/include/linux/irqchip/mips-gic.h
@@ -45,8 +45,14 @@
 #define GIC_SH_REVISIONID_OFS		0x0020
 
 /* Convert an interrupt number to a byte offset/bit for multi-word registers */
-#define GIC_INTR_OFS(intr)		(((intr) / 32) * 4)
-#define GIC_INTR_BIT(intr)		((intr) % 32)
+#define GIC_INTR_OFS(intr) ({				\
+	unsigned bits = mips_cm_is64 ? 64 : 32;		\
+	unsigned reg_idx = (intr) / bits;		\
+	unsigned reg_width = bits / 8;			\
+							\
+	reg_idx * reg_width;				\
+})
+#define GIC_INTR_BIT(intr)		((intr) % (mips_cm_is64 ? 64 : 32))
 
 /* Polarity : Reset Value is always 0 */
 #define GIC_SH_SET_POLARITY_OFS		0x0100
-- 
2.4.5

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

* [PATCH 15/19] drivers: irqchip: irq-mips-gic: Add support for CM3 64-bit timer irqs
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips
  Cc: Markos Chandras, Thomas Gleixner, Jason Cooper, Andrew Bresticker

CM3 uses a 64-bit counter and compare registers so add support for
them in the GIC counter interrupt.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Bresticker <abrestic@chromium.org>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 drivers/irqchip/irq-mips-gic.c   | 33 ++++++++++++++++++++++++---------
 include/linux/irqchip/mips-gic.h |  4 ++++
 2 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 29c494691b71..def7a9be36a0 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -140,6 +140,9 @@ cycle_t gic_read_count(void)
 {
 	unsigned int hi, hi2, lo;
 
+	if (mips_cm_is64)
+		return (cycle_t)gic_read(GIC_REG(SHARED, GIC_SH_COUNTER));
+
 	do {
 		hi = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
 		lo = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_31_00));
@@ -162,10 +165,14 @@ unsigned int gic_get_count_width(void)
 
 void gic_write_compare(cycle_t cnt)
 {
-	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
-				(int)(cnt >> 32));
-	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
-				(int)(cnt & 0xffffffff));
+	if (mips_cm_is64) {
+		gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE), cnt);
+	} else {
+		gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
+					(int)(cnt >> 32));
+		gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
+					(int)(cnt & 0xffffffff));
+	}
 }
 
 void gic_write_cpu_compare(cycle_t cnt, int cpu)
@@ -174,11 +181,16 @@ void gic_write_cpu_compare(cycle_t cnt, int cpu)
 
 	local_irq_save(flags);
 
-	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
-	gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
-				(int)(cnt >> 32));
-	gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
-				(int)(cnt & 0xffffffff));
+	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
+
+	if (mips_cm_is64) {
+		gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE), cnt);
+	} else {
+		gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
+					(int)(cnt >> 32));
+		gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
+					(int)(cnt & 0xffffffff));
+	}
 
 	local_irq_restore(flags);
 }
@@ -187,6 +199,9 @@ cycle_t gic_read_compare(void)
 {
 	unsigned int hi, lo;
 
+	if (mips_cm_is64)
+		return (cycle_t)gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE));
+
 	hi = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI));
 	lo = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO));
 
diff --git a/include/linux/irqchip/mips-gic.h b/include/linux/irqchip/mips-gic.h
index 10e4a9073019..4e6861605050 100644
--- a/include/linux/irqchip/mips-gic.h
+++ b/include/linux/irqchip/mips-gic.h
@@ -41,6 +41,8 @@
 
 /* Shared Global Counter */
 #define GIC_SH_COUNTER_31_00_OFS	0x0010
+/* 64-bit counter register for CM3 */
+#define GIC_SH_COUNTER_OFS		GIC_SH_COUNTER_31_00_OFS
 #define GIC_SH_COUNTER_63_32_OFS	0x0014
 #define GIC_SH_REVISIONID_OFS		0x0020
 
@@ -104,6 +106,8 @@
 #define GIC_VPE_WD_COUNT0_OFS		0x0094
 #define GIC_VPE_WD_INITIAL0_OFS		0x0098
 #define GIC_VPE_COMPARE_LO_OFS		0x00a0
+/* 64-bit Compare register on CM3 */
+#define GIC_VPE_COMPARE_OFS		GIC_VPE_COMPARE_LO_OFS
 #define GIC_VPE_COMPARE_HI_OFS		0x00a4
 
 #define GIC_VPE_EIC_SHADOW_SET_BASE_OFS	0x0100
-- 
2.4.5

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

* [PATCH 15/19] drivers: irqchip: irq-mips-gic: Add support for CM3 64-bit timer irqs
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips
  Cc: Markos Chandras, Thomas Gleixner, Jason Cooper, Andrew Bresticker

CM3 uses a 64-bit counter and compare registers so add support for
them in the GIC counter interrupt.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Bresticker <abrestic@chromium.org>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 drivers/irqchip/irq-mips-gic.c   | 33 ++++++++++++++++++++++++---------
 include/linux/irqchip/mips-gic.h |  4 ++++
 2 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 29c494691b71..def7a9be36a0 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -140,6 +140,9 @@ cycle_t gic_read_count(void)
 {
 	unsigned int hi, hi2, lo;
 
+	if (mips_cm_is64)
+		return (cycle_t)gic_read(GIC_REG(SHARED, GIC_SH_COUNTER));
+
 	do {
 		hi = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
 		lo = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_31_00));
@@ -162,10 +165,14 @@ unsigned int gic_get_count_width(void)
 
 void gic_write_compare(cycle_t cnt)
 {
-	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
-				(int)(cnt >> 32));
-	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
-				(int)(cnt & 0xffffffff));
+	if (mips_cm_is64) {
+		gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE), cnt);
+	} else {
+		gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
+					(int)(cnt >> 32));
+		gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
+					(int)(cnt & 0xffffffff));
+	}
 }
 
 void gic_write_cpu_compare(cycle_t cnt, int cpu)
@@ -174,11 +181,16 @@ void gic_write_cpu_compare(cycle_t cnt, int cpu)
 
 	local_irq_save(flags);
 
-	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
-	gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
-				(int)(cnt >> 32));
-	gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
-				(int)(cnt & 0xffffffff));
+	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
+
+	if (mips_cm_is64) {
+		gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE), cnt);
+	} else {
+		gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
+					(int)(cnt >> 32));
+		gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
+					(int)(cnt & 0xffffffff));
+	}
 
 	local_irq_restore(flags);
 }
@@ -187,6 +199,9 @@ cycle_t gic_read_compare(void)
 {
 	unsigned int hi, lo;
 
+	if (mips_cm_is64)
+		return (cycle_t)gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE));
+
 	hi = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI));
 	lo = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO));
 
diff --git a/include/linux/irqchip/mips-gic.h b/include/linux/irqchip/mips-gic.h
index 10e4a9073019..4e6861605050 100644
--- a/include/linux/irqchip/mips-gic.h
+++ b/include/linux/irqchip/mips-gic.h
@@ -41,6 +41,8 @@
 
 /* Shared Global Counter */
 #define GIC_SH_COUNTER_31_00_OFS	0x0010
+/* 64-bit counter register for CM3 */
+#define GIC_SH_COUNTER_OFS		GIC_SH_COUNTER_31_00_OFS
 #define GIC_SH_COUNTER_63_32_OFS	0x0014
 #define GIC_SH_REVISIONID_OFS		0x0020
 
@@ -104,6 +106,8 @@
 #define GIC_VPE_WD_COUNT0_OFS		0x0094
 #define GIC_VPE_WD_INITIAL0_OFS		0x0098
 #define GIC_VPE_COMPARE_LO_OFS		0x00a0
+/* 64-bit Compare register on CM3 */
+#define GIC_VPE_COMPARE_OFS		GIC_VPE_COMPARE_LO_OFS
 #define GIC_VPE_COMPARE_HI_OFS		0x00a4
 
 #define GIC_VPE_EIC_SHADOW_SET_BASE_OFS	0x0100
-- 
2.4.5

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

* [PATCH 16/19] MIPS: kernel: cpu-probe: Remove cp0 hazard barrier when enabling the FTLB
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

We are so early in the boot process where we really don't want to
stall and wait for CP0 FTLB related changes become visible so just drop
the cp0 hazard barrier.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cpu-probe.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 02b75127dad3..dc057f37305b 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -385,7 +385,6 @@ static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
 		else
 			/* Disable FTLB */
 			write_c0_config6(config6 &  ~MIPS_CONF6_FTLBEN);
-		back_to_back_c0_hazard();
 		break;
 	}
 }
-- 
2.4.5

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

* [PATCH 16/19] MIPS: kernel: cpu-probe: Remove cp0 hazard barrier when enabling the FTLB
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

We are so early in the boot process where we really don't want to
stall and wait for CP0 FTLB related changes become visible so just drop
the cp0 hazard barrier.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cpu-probe.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 02b75127dad3..dc057f37305b 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -385,7 +385,6 @@ static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
 		else
 			/* Disable FTLB */
 			write_c0_config6(config6 &  ~MIPS_CONF6_FTLBEN);
-		back_to_back_c0_hazard();
 		break;
 	}
 }
-- 
2.4.5

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

* [PATCH 17/19] MIPS: Add default case for the FTLB enable/disable code
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add a default case for the FTLB enable/disable code. This will be used
to detect that something went wrong in the set_ftlb_enable() function
either because that function knows nothing about the running core, or
simply because the core can't turn its FTLB on/off.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cpu-probe.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index dc057f37305b..6da5f2db6792 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -188,7 +188,7 @@ __setup("nohtw", htw_disable);
 static int mips_ftlb_disabled;
 static int mips_has_ftlb_configured;
 
-static void set_ftlb_enable(struct cpuinfo_mips *c, int enable);
+static int set_ftlb_enable(struct cpuinfo_mips *c, int enable);
 
 static int __init ftlb_disable(char *s)
 {
@@ -202,7 +202,10 @@ static int __init ftlb_disable(char *s)
 		return 1;
 
 	/* Disable it in the boot cpu */
-	set_ftlb_enable(&cpu_data[0], 0);
+	if (set_ftlb_enable(&cpu_data[0], 0)) {
+		pr_warn("Can't turn FTLB off\n");
+		return 1;
+	}
 
 	back_to_back_c0_hazard();
 
@@ -364,7 +367,7 @@ static unsigned int calculate_ftlb_probability(struct cpuinfo_mips *c)
 		return 3;
 }
 
-static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
+static int set_ftlb_enable(struct cpuinfo_mips *c, int enable)
 {
 	unsigned int config6;
 
@@ -386,7 +389,11 @@ static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
 			/* Disable FTLB */
 			write_c0_config6(config6 &  ~MIPS_CONF6_FTLBEN);
 		break;
+	default:
+		return 1;
 	}
+
+	return 0;
 }
 
 static inline unsigned int decode_config0(struct cpuinfo_mips *c)
-- 
2.4.5

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

* [PATCH 17/19] MIPS: Add default case for the FTLB enable/disable code
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Add a default case for the FTLB enable/disable code. This will be used
to detect that something went wrong in the set_ftlb_enable() function
either because that function knows nothing about the running core, or
simply because the core can't turn its FTLB on/off.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cpu-probe.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index dc057f37305b..6da5f2db6792 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -188,7 +188,7 @@ __setup("nohtw", htw_disable);
 static int mips_ftlb_disabled;
 static int mips_has_ftlb_configured;
 
-static void set_ftlb_enable(struct cpuinfo_mips *c, int enable);
+static int set_ftlb_enable(struct cpuinfo_mips *c, int enable);
 
 static int __init ftlb_disable(char *s)
 {
@@ -202,7 +202,10 @@ static int __init ftlb_disable(char *s)
 		return 1;
 
 	/* Disable it in the boot cpu */
-	set_ftlb_enable(&cpu_data[0], 0);
+	if (set_ftlb_enable(&cpu_data[0], 0)) {
+		pr_warn("Can't turn FTLB off\n");
+		return 1;
+	}
 
 	back_to_back_c0_hazard();
 
@@ -364,7 +367,7 @@ static unsigned int calculate_ftlb_probability(struct cpuinfo_mips *c)
 		return 3;
 }
 
-static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
+static int set_ftlb_enable(struct cpuinfo_mips *c, int enable)
 {
 	unsigned int config6;
 
@@ -386,7 +389,11 @@ static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
 			/* Disable FTLB */
 			write_c0_config6(config6 &  ~MIPS_CONF6_FTLBEN);
 		break;
+	default:
+		return 1;
 	}
+
+	return 0;
 }
 
 static inline unsigned int decode_config0(struct cpuinfo_mips *c)
-- 
2.4.5

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

* [PATCH 18/19] MIPS: kernel: cpu-probe: Fix VTLB/FTLB configuration for R6
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

R6 has dropped the MMUExtDef field from the config4 register and it
now returns 0. However, the return value means nothing in that case
and the only supported configuration for R6 is the VTLB+FTLB
(MMUextDef == 3). As a result, rework the code so that the correct
value is set for R6 cores.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cpu-probe.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 6da5f2db6792..62dae429fe70 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -546,7 +546,16 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
 	if (cpu_has_tlb) {
 		if (((config4 & MIPS_CONF4_IE) >> 29) == 2)
 			c->options |= MIPS_CPU_TLBINV;
-		mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
+		/*
+		 * This is a bit ugly. R6 has dropped that field from
+		 * config4 and the only valid configuration is VTLB+FTLB so
+		 * set a good value for mmuextdef for that case.
+		 */
+		if (cpu_has_mips_r6)
+			mmuextdef = MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT;
+		else
+			mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
+
 		switch (mmuextdef) {
 		case MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT:
 			c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
-- 
2.4.5

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

* [PATCH 18/19] MIPS: kernel: cpu-probe: Fix VTLB/FTLB configuration for R6
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

R6 has dropped the MMUExtDef field from the config4 register and it
now returns 0. However, the return value means nothing in that case
and the only supported configuration for R6 is the VTLB+FTLB
(MMUextDef == 3). As a result, rework the code so that the correct
value is set for R6 cores.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/kernel/cpu-probe.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 6da5f2db6792..62dae429fe70 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -546,7 +546,16 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
 	if (cpu_has_tlb) {
 		if (((config4 & MIPS_CONF4_IE) >> 29) == 2)
 			c->options |= MIPS_CPU_TLBINV;
-		mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
+		/*
+		 * This is a bit ugly. R6 has dropped that field from
+		 * config4 and the only valid configuration is VTLB+FTLB so
+		 * set a good value for mmuextdef for that case.
+		 */
+		if (cpu_has_mips_r6)
+			mmuextdef = MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT;
+		else
+			mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
+
 		switch (mmuextdef) {
 		case MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT:
 			c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
-- 
2.4.5

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

* [PATCH 19/19] MIPS: Set up FTLB probability for I6400
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Set up the I6400 FTLB probability similar to P5600 and proAptiv.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/mipsregs.h |  2 ++
 arch/mips/kernel/cpu-probe.c     | 18 +++++++++++++-----
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index c5b0956a8530..723ee3c7849d 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -579,6 +579,8 @@
 
 #define MIPS_CONF7_IAR		(_ULCAST_(1) << 10)
 #define MIPS_CONF7_AR		(_ULCAST_(1) << 16)
+/* FTLB probability bits for R6 */
+#define MIPS_CONF7_FTLBP_SHIFT	(18)
 
 /* MAAR bit definitions */
 #define MIPS_MAAR_ADDR		((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 62dae429fe70..4e39b340f3b7 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -369,25 +369,33 @@ static unsigned int calculate_ftlb_probability(struct cpuinfo_mips *c)
 
 static int set_ftlb_enable(struct cpuinfo_mips *c, int enable)
 {
-	unsigned int config6;
+	unsigned int config;
 
 	/* It's implementation dependent how the FTLB can be enabled */
 	switch (c->cputype) {
 	case CPU_PROAPTIV:
 	case CPU_P5600:
 		/* proAptiv & related cores use Config6 to enable the FTLB */
-		config6 = read_c0_config6();
+		config = read_c0_config6();
 		/* Clear the old probability value */
-		config6 &= ~(3 << MIPS_CONF6_FTLBP_SHIFT);
+		config &= ~(3 << MIPS_CONF6_FTLBP_SHIFT);
 		if (enable)
 			/* Enable FTLB */
-			write_c0_config6(config6 |
+			write_c0_config6(config |
 					 (calculate_ftlb_probability(c)
 					  << MIPS_CONF6_FTLBP_SHIFT)
 					 | MIPS_CONF6_FTLBEN);
 		else
 			/* Disable FTLB */
-			write_c0_config6(config6 &  ~MIPS_CONF6_FTLBEN);
+			write_c0_config6(config &  ~MIPS_CONF6_FTLBEN);
+		break;
+	case CPU_I6400:
+		/* I6400 & related cores use Config7 to configure FTLB */
+		config = read_c0_config7();
+		/* Clear the old probability value */
+		config &= ~(3 << MIPS_CONF7_FTLBP_SHIFT);
+		write_c0_config7(config | (calculate_ftlb_probability(c)
+					   << MIPS_CONF7_FTLBP_SHIFT));
 		break;
 	default:
 		return 1;
-- 
2.4.5

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

* [PATCH 19/19] MIPS: Set up FTLB probability for I6400
@ 2015-07-09  9:40   ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09  9:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Markos Chandras

Set up the I6400 FTLB probability similar to P5600 and proAptiv.

Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
 arch/mips/include/asm/mipsregs.h |  2 ++
 arch/mips/kernel/cpu-probe.c     | 18 +++++++++++++-----
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index c5b0956a8530..723ee3c7849d 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -579,6 +579,8 @@
 
 #define MIPS_CONF7_IAR		(_ULCAST_(1) << 10)
 #define MIPS_CONF7_AR		(_ULCAST_(1) << 16)
+/* FTLB probability bits for R6 */
+#define MIPS_CONF7_FTLBP_SHIFT	(18)
 
 /* MAAR bit definitions */
 #define MIPS_MAAR_ADDR		((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 62dae429fe70..4e39b340f3b7 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -369,25 +369,33 @@ static unsigned int calculate_ftlb_probability(struct cpuinfo_mips *c)
 
 static int set_ftlb_enable(struct cpuinfo_mips *c, int enable)
 {
-	unsigned int config6;
+	unsigned int config;
 
 	/* It's implementation dependent how the FTLB can be enabled */
 	switch (c->cputype) {
 	case CPU_PROAPTIV:
 	case CPU_P5600:
 		/* proAptiv & related cores use Config6 to enable the FTLB */
-		config6 = read_c0_config6();
+		config = read_c0_config6();
 		/* Clear the old probability value */
-		config6 &= ~(3 << MIPS_CONF6_FTLBP_SHIFT);
+		config &= ~(3 << MIPS_CONF6_FTLBP_SHIFT);
 		if (enable)
 			/* Enable FTLB */
-			write_c0_config6(config6 |
+			write_c0_config6(config |
 					 (calculate_ftlb_probability(c)
 					  << MIPS_CONF6_FTLBP_SHIFT)
 					 | MIPS_CONF6_FTLBEN);
 		else
 			/* Disable FTLB */
-			write_c0_config6(config6 &  ~MIPS_CONF6_FTLBEN);
+			write_c0_config6(config &  ~MIPS_CONF6_FTLBEN);
+		break;
+	case CPU_I6400:
+		/* I6400 & related cores use Config7 to configure FTLB */
+		config = read_c0_config7();
+		/* Clear the old probability value */
+		config &= ~(3 << MIPS_CONF7_FTLBP_SHIFT);
+		write_c0_config7(config | (calculate_ftlb_probability(c)
+					   << MIPS_CONF7_FTLBP_SHIFT));
 		break;
 	default:
 		return 1;
-- 
2.4.5

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

* Re: [PATCH 02/19] MIPS: Add cases for CPU_I6400
  2015-07-09  9:40   ` Markos Chandras
  (?)
@ 2015-07-09 10:03   ` Ralf Baechle
  2015-07-09 10:14       ` Markos Chandras
  -1 siblings, 1 reply; 65+ messages in thread
From: Ralf Baechle @ 2015-07-09 10:03 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On Thu, Jul 09, 2015 at 10:40:36AM +0100, Markos Chandras wrote:

> index d41e8e284825..abee2bfd10dc 100644
> --- a/arch/mips/include/asm/cpu-type.h
> +++ b/arch/mips/include/asm/cpu-type.h
> @@ -77,6 +77,10 @@ static inline int __pure __get_cpu_type(const int cpu_type)
>  	 */
>  #endif
>  
> +#ifdef CONFIG_SYS_HAS_CPU_MIPS64_R6
> +	case CPU_I6400:
> +#endif
> +

To ensure best possible optimization you may want to introduce a new
CPU type CPU_I6400 in Kconfig then change above code segment to

#ifdef CONFIG_SYS_HAS_CPU_I6400
	case CPU_I6400:
#endif

__get_cpu_type is ideally meant to get folded to a constant on any
particular platform which then will allow the compiler to discard lots
of other code.

Of course Malta being as hetergenous as it is that's not goint help
with Malta but it will make a noticable difference for SOCs which usually
come only with a single supported CPU type.

  Ralf

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

* Re: [PATCH 02/19] MIPS: Add cases for CPU_I6400
@ 2015-07-09 10:14       ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09 10:14 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

On 07/09/2015 11:03 AM, Ralf Baechle wrote:
> On Thu, Jul 09, 2015 at 10:40:36AM +0100, Markos Chandras wrote:
> 
>> index d41e8e284825..abee2bfd10dc 100644
>> --- a/arch/mips/include/asm/cpu-type.h
>> +++ b/arch/mips/include/asm/cpu-type.h
>> @@ -77,6 +77,10 @@ static inline int __pure __get_cpu_type(const int cpu_type)
>>  	 */
>>  #endif
>>  
>> +#ifdef CONFIG_SYS_HAS_CPU_MIPS64_R6
>> +	case CPU_I6400:
>> +#endif
>> +
> 
> To ensure best possible optimization you may want to introduce a new
> CPU type CPU_I6400 in Kconfig then change above code segment to
> 
> #ifdef CONFIG_SYS_HAS_CPU_I6400
> 	case CPU_I6400:
> #endif
> 

Why? That function uses MIPS32_XX and MIPS64_XX in other places as well.

I don't think it's a good idea to have a Kconfig symbol for I6400. It's
just a MIPSR6 processor so we do the same thing we did for other
processors like P5600, interAptiv etc.

> __get_cpu_type is ideally meant to get folded to a constant on any
> particular platform which then will allow the compiler to discard lots
> of other code.
> 
> Of course Malta being as hetergenous as it is that's not goint help
> with Malta but it will make a noticable difference for SOCs which usually
> come only with a single supported CPU type.
> 
>   Ralf
> 
Then it's best if we use platform Kconfig symbols in that function
instead of introducing a new symbol per processor.

-- 
markos

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

* Re: [PATCH 02/19] MIPS: Add cases for CPU_I6400
@ 2015-07-09 10:14       ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09 10:14 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

On 07/09/2015 11:03 AM, Ralf Baechle wrote:
> On Thu, Jul 09, 2015 at 10:40:36AM +0100, Markos Chandras wrote:
> 
>> index d41e8e284825..abee2bfd10dc 100644
>> --- a/arch/mips/include/asm/cpu-type.h
>> +++ b/arch/mips/include/asm/cpu-type.h
>> @@ -77,6 +77,10 @@ static inline int __pure __get_cpu_type(const int cpu_type)
>>  	 */
>>  #endif
>>  
>> +#ifdef CONFIG_SYS_HAS_CPU_MIPS64_R6
>> +	case CPU_I6400:
>> +#endif
>> +
> 
> To ensure best possible optimization you may want to introduce a new
> CPU type CPU_I6400 in Kconfig then change above code segment to
> 
> #ifdef CONFIG_SYS_HAS_CPU_I6400
> 	case CPU_I6400:
> #endif
> 

Why? That function uses MIPS32_XX and MIPS64_XX in other places as well.

I don't think it's a good idea to have a Kconfig symbol for I6400. It's
just a MIPSR6 processor so we do the same thing we did for other
processors like P5600, interAptiv etc.

> __get_cpu_type is ideally meant to get folded to a constant on any
> particular platform which then will allow the compiler to discard lots
> of other code.
> 
> Of course Malta being as hetergenous as it is that's not goint help
> with Malta but it will make a noticable difference for SOCs which usually
> come only with a single supported CPU type.
> 
>   Ralf
> 
Then it's best if we use platform Kconfig symbols in that function
instead of introducing a new symbol per processor.

-- 
markos

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

* Re: [PATCH 05/19] MIPS: asm: mips-cm: Implement mips_cm_revision
  2015-07-09  9:40   ` Markos Chandras
  (?)
@ 2015-07-09 11:09   ` Sergei Shtylyov
  2015-07-09 16:05       ` Markos Chandras
  -1 siblings, 1 reply; 65+ messages in thread
From: Sergei Shtylyov @ 2015-07-09 11:09 UTC (permalink / raw)
  To: Markos Chandras, linux-mips; +Cc: Paul Burton

On 7/9/2015 12:40 PM, Markos Chandras wrote:

> From: Paul Burton <paul.burton@imgtec.com>

> Provide a function to trivially return the version of the CM present in
> the system, or 0 if no CM is present. The mips_cm_revision() will be
> used later on to determine the CM register width, so it must not use
> the regular CM accessors to read the revision register since that will
> lead to build failures due to recursive inlines.

> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>   arch/mips/include/asm/mips-cm.h | 29 +++++++++++++++++++++++++++++
>   1 file changed, 29 insertions(+)

> diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
> index edc7ee95269e..29ff74a629f6 100644
> --- a/arch/mips/include/asm/mips-cm.h
> +++ b/arch/mips/include/asm/mips-cm.h
> @@ -189,6 +189,13 @@ BUILD_CM_Cx_R_(tcid_8_priority,	0x80)
>   #define CM_GCR_REV_MINOR_SHF			0
>   #define CM_GCR_REV_MINOR_MSK			(_ULCAST_(0xff) << 0)
>
> +#define CM_ENCODE_REV(major, minor) \
> +		((major << CM_GCR_REV_MAJOR_SHF) | \
> +		 ((minor) << CM_GCR_REV_MINOR_SHF))

    Enclosing 'minor' into parens and not enclosing 'major' doesn't look very 
consistent... :-)

[...]
> @@ -324,4 +331,26 @@ static inline int mips_cm_l2sync(void)
>   	return 0;
>   }
>
> +/**
> + * mips_cm_revision - return CM revision
> + *
> + * Returns the revision of the CM, from GCR_REV, or 0 if no CM is present.
> + * The return value should be checked against the CM_REV_* macros.
> + */
> +static inline int mips_cm_revision(void)
> +{
> +	static int mips_cm_revision_nr = -1;

    Won't this variable be allocated per source file (including this header)?

[...]

WBR, Sergei

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

* Re: [PATCH 05/19] MIPS: asm: mips-cm: Implement mips_cm_revision
@ 2015-07-09 11:29     ` James Hogan
  0 siblings, 0 replies; 65+ messages in thread
From: James Hogan @ 2015-07-09 11:29 UTC (permalink / raw)
  To: Markos Chandras, linux-mips; +Cc: Paul Burton

[-- Attachment #1: Type: text/plain, Size: 2367 bytes --]

Hi Markos,

On 09/07/15 10:40, Markos Chandras wrote:
> From: Paul Burton <paul.burton@imgtec.com>
> 
> Provide a function to trivially return the version of the CM present in
> the system, or 0 if no CM is present. The mips_cm_revision() will be
> used later on to determine the CM register width, so it must not use
> the regular CM accessors to read the revision register since that will
> lead to build failures due to recursive inlines.
> 
> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>  arch/mips/include/asm/mips-cm.h | 29 +++++++++++++++++++++++++++++
>  1 file changed, 29 insertions(+)
> 
> diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
> index edc7ee95269e..29ff74a629f6 100644
> --- a/arch/mips/include/asm/mips-cm.h
> +++ b/arch/mips/include/asm/mips-cm.h
> @@ -189,6 +189,13 @@ BUILD_CM_Cx_R_(tcid_8_priority,	0x80)
>  #define CM_GCR_REV_MINOR_SHF			0
>  #define CM_GCR_REV_MINOR_MSK			(_ULCAST_(0xff) << 0)
>  
> +#define CM_ENCODE_REV(major, minor) \
> +		((major << CM_GCR_REV_MAJOR_SHF) | \
> +		 ((minor) << CM_GCR_REV_MINOR_SHF))
> +
> +#define CM_REV_CM2				CM_ENCODE_REV(6, 0)
> +#define CM_REV_CM3				CM_ENCODE_REV(8, 0)
> +
>  /* GCR_ERROR_CAUSE register fields */
>  #define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF		27
>  #define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK		(_ULCAST_(0x1f) << 27)
> @@ -324,4 +331,26 @@ static inline int mips_cm_l2sync(void)
>  	return 0;
>  }
>  
> +/**
> + * mips_cm_revision - return CM revision

don't forget brackets: "mips_cm_revision()"

> + *
> + * Returns the revision of the CM, from GCR_REV, or 0 if no CM is present.
> + * The return value should be checked against the CM_REV_* macros.

Use "Return: bla bla bla." so it lands in a nice return section.

see Documentation/kernel-doc-nano-HOWTO.txt for an example.

Cheers
James

> + */
> +static inline int mips_cm_revision(void)
> +{
> +	static int mips_cm_revision_nr = -1;
> +
> +	/* No need to read that register over and over */
> +	if (mips_cm_revision_nr >= 0)
> +		return mips_cm_revision_nr;
> +
> +	if (!mips_cm_present())
> +		return 0;
> +
> +	mips_cm_revision_nr = read_gcr_rev();
> +
> +	return mips_cm_revision_nr;
> +}
> +
>  #endif /* __MIPS_ASM_MIPS_CM_H__ */
> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH 05/19] MIPS: asm: mips-cm: Implement mips_cm_revision
@ 2015-07-09 11:29     ` James Hogan
  0 siblings, 0 replies; 65+ messages in thread
From: James Hogan @ 2015-07-09 11:29 UTC (permalink / raw)
  To: Markos Chandras, linux-mips; +Cc: Paul Burton

[-- Attachment #1: Type: text/plain, Size: 2367 bytes --]

Hi Markos,

On 09/07/15 10:40, Markos Chandras wrote:
> From: Paul Burton <paul.burton@imgtec.com>
> 
> Provide a function to trivially return the version of the CM present in
> the system, or 0 if no CM is present. The mips_cm_revision() will be
> used later on to determine the CM register width, so it must not use
> the regular CM accessors to read the revision register since that will
> lead to build failures due to recursive inlines.
> 
> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
>  arch/mips/include/asm/mips-cm.h | 29 +++++++++++++++++++++++++++++
>  1 file changed, 29 insertions(+)
> 
> diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
> index edc7ee95269e..29ff74a629f6 100644
> --- a/arch/mips/include/asm/mips-cm.h
> +++ b/arch/mips/include/asm/mips-cm.h
> @@ -189,6 +189,13 @@ BUILD_CM_Cx_R_(tcid_8_priority,	0x80)
>  #define CM_GCR_REV_MINOR_SHF			0
>  #define CM_GCR_REV_MINOR_MSK			(_ULCAST_(0xff) << 0)
>  
> +#define CM_ENCODE_REV(major, minor) \
> +		((major << CM_GCR_REV_MAJOR_SHF) | \
> +		 ((minor) << CM_GCR_REV_MINOR_SHF))
> +
> +#define CM_REV_CM2				CM_ENCODE_REV(6, 0)
> +#define CM_REV_CM3				CM_ENCODE_REV(8, 0)
> +
>  /* GCR_ERROR_CAUSE register fields */
>  #define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF		27
>  #define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK		(_ULCAST_(0x1f) << 27)
> @@ -324,4 +331,26 @@ static inline int mips_cm_l2sync(void)
>  	return 0;
>  }
>  
> +/**
> + * mips_cm_revision - return CM revision

don't forget brackets: "mips_cm_revision()"

> + *
> + * Returns the revision of the CM, from GCR_REV, or 0 if no CM is present.
> + * The return value should be checked against the CM_REV_* macros.

Use "Return: bla bla bla." so it lands in a nice return section.

see Documentation/kernel-doc-nano-HOWTO.txt for an example.

Cheers
James

> + */
> +static inline int mips_cm_revision(void)
> +{
> +	static int mips_cm_revision_nr = -1;
> +
> +	/* No need to read that register over and over */
> +	if (mips_cm_revision_nr >= 0)
> +		return mips_cm_revision_nr;
> +
> +	if (!mips_cm_present())
> +		return 0;
> +
> +	mips_cm_revision_nr = read_gcr_rev();
> +
> +	return mips_cm_revision_nr;
> +}
> +
>  #endif /* __MIPS_ASM_MIPS_CM_H__ */
> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH 02/19] MIPS: Add cases for CPU_I6400
  2015-07-09 10:14       ` Markos Chandras
  (?)
@ 2015-07-09 11:43       ` Ralf Baechle
  -1 siblings, 0 replies; 65+ messages in thread
From: Ralf Baechle @ 2015-07-09 11:43 UTC (permalink / raw)
  To: Markos Chandras; +Cc: linux-mips

On Thu, Jul 09, 2015 at 11:14:54AM +0100, Markos Chandras wrote:

> On 07/09/2015 11:03 AM, Ralf Baechle wrote:
> > On Thu, Jul 09, 2015 at 10:40:36AM +0100, Markos Chandras wrote:
> > 
> >> index d41e8e284825..abee2bfd10dc 100644
> >> --- a/arch/mips/include/asm/cpu-type.h
> >> +++ b/arch/mips/include/asm/cpu-type.h
> >> @@ -77,6 +77,10 @@ static inline int __pure __get_cpu_type(const int cpu_type)
> >>  	 */
> >>  #endif
> >>  
> >> +#ifdef CONFIG_SYS_HAS_CPU_MIPS64_R6
> >> +	case CPU_I6400:
> >> +#endif
> >> +
> > 
> > To ensure best possible optimization you may want to introduce a new
> > CPU type CPU_I6400 in Kconfig then change above code segment to
> > 
> > #ifdef CONFIG_SYS_HAS_CPU_I6400
> > 	case CPU_I6400:
> > #endif
> > 
> 
> Why? That function uses MIPS32_XX and MIPS64_XX in other places as well.

This is one matters a lot for optimization by GCC.

Currently you're ok for as long as The I6400 stays the sole CPU wrapped
by #ifdef CONFIG_SYS_HAS_CPU_MIPS64_R6.  As soon as another CPU becomes
does the same optimization will suffer.

Example:

#ifdef CONFIG_SYS_HAS_CPU_MIPS32_R1
        case CPU_4KC:
        case CPU_ALCHEMY:
        case CPU_PR4450:
#endif

GCC is clever enough these days to figure out that __get_cpu_type() will
only return certain values so it will do some optimization but the best
case of course is if __get_cpu_type() returns one value only.

  Ralf

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

* Re: [PATCH 05/19] MIPS: asm: mips-cm: Implement mips_cm_revision
@ 2015-07-09 16:05       ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09 16:05 UTC (permalink / raw)
  To: Sergei Shtylyov, linux-mips; +Cc: Paul Burton

On 07/09/2015 12:09 PM, Sergei Shtylyov wrote:
> On 7/9/2015 12:40 PM, Markos Chandras wrote:
> 
>> From: Paul Burton <paul.burton@imgtec.com>
> 
>> Provide a function to trivially return the version of the CM present in
>> the system, or 0 if no CM is present. The mips_cm_revision() will be
>> used later on to determine the CM register width, so it must not use
>> the regular CM accessors to read the revision register since that will
>> lead to build failures due to recursive inlines.
> 
>> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>>   arch/mips/include/asm/mips-cm.h | 29 +++++++++++++++++++++++++++++
>>   1 file changed, 29 insertions(+)
> 
>> diff --git a/arch/mips/include/asm/mips-cm.h
>> b/arch/mips/include/asm/mips-cm.h
>> index edc7ee95269e..29ff74a629f6 100644
>> --- a/arch/mips/include/asm/mips-cm.h
>> +++ b/arch/mips/include/asm/mips-cm.h
>> @@ -189,6 +189,13 @@ BUILD_CM_Cx_R_(tcid_8_priority,    0x80)
>>   #define CM_GCR_REV_MINOR_SHF            0
>>   #define CM_GCR_REV_MINOR_MSK            (_ULCAST_(0xff) << 0)
>>
>> +#define CM_ENCODE_REV(major, minor) \
>> +        ((major << CM_GCR_REV_MAJOR_SHF) | \
>> +         ((minor) << CM_GCR_REV_MINOR_SHF))
> 
>    Enclosing 'minor' into parens and not enclosing 'major' doesn't look
> very consistent... :-)

Ok I will fix it

> 
> [...]
>> @@ -324,4 +331,26 @@ static inline int mips_cm_l2sync(void)
>>       return 0;
>>   }
>>
>> +/**
>> + * mips_cm_revision - return CM revision
>> + *
>> + * Returns the revision of the CM, from GCR_REV, or 0 if no CM is
>> present.
>> + * The return value should be checked against the CM_REV_* macros.
>> + */
>> +static inline int mips_cm_revision(void)
>> +{
>> +    static int mips_cm_revision_nr = -1;
> 
>    Won't this variable be allocated per source file (including this
> header)?

I will drop the static variable since the implementation changed
overtime and there is no need to call mips_cm_revision() so often anymore.


-- 
markos

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

* Re: [PATCH 05/19] MIPS: asm: mips-cm: Implement mips_cm_revision
@ 2015-07-09 16:05       ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09 16:05 UTC (permalink / raw)
  To: Sergei Shtylyov, linux-mips; +Cc: Paul Burton

On 07/09/2015 12:09 PM, Sergei Shtylyov wrote:
> On 7/9/2015 12:40 PM, Markos Chandras wrote:
> 
>> From: Paul Burton <paul.burton@imgtec.com>
> 
>> Provide a function to trivially return the version of the CM present in
>> the system, or 0 if no CM is present. The mips_cm_revision() will be
>> used later on to determine the CM register width, so it must not use
>> the regular CM accessors to read the revision register since that will
>> lead to build failures due to recursive inlines.
> 
>> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>>   arch/mips/include/asm/mips-cm.h | 29 +++++++++++++++++++++++++++++
>>   1 file changed, 29 insertions(+)
> 
>> diff --git a/arch/mips/include/asm/mips-cm.h
>> b/arch/mips/include/asm/mips-cm.h
>> index edc7ee95269e..29ff74a629f6 100644
>> --- a/arch/mips/include/asm/mips-cm.h
>> +++ b/arch/mips/include/asm/mips-cm.h
>> @@ -189,6 +189,13 @@ BUILD_CM_Cx_R_(tcid_8_priority,    0x80)
>>   #define CM_GCR_REV_MINOR_SHF            0
>>   #define CM_GCR_REV_MINOR_MSK            (_ULCAST_(0xff) << 0)
>>
>> +#define CM_ENCODE_REV(major, minor) \
>> +        ((major << CM_GCR_REV_MAJOR_SHF) | \
>> +         ((minor) << CM_GCR_REV_MINOR_SHF))
> 
>    Enclosing 'minor' into parens and not enclosing 'major' doesn't look
> very consistent... :-)

Ok I will fix it

> 
> [...]
>> @@ -324,4 +331,26 @@ static inline int mips_cm_l2sync(void)
>>       return 0;
>>   }
>>
>> +/**
>> + * mips_cm_revision - return CM revision
>> + *
>> + * Returns the revision of the CM, from GCR_REV, or 0 if no CM is
>> present.
>> + * The return value should be checked against the CM_REV_* macros.
>> + */
>> +static inline int mips_cm_revision(void)
>> +{
>> +    static int mips_cm_revision_nr = -1;
> 
>    Won't this variable be allocated per source file (including this
> header)?

I will drop the static variable since the implementation changed
overtime and there is no need to call mips_cm_revision() so often anymore.


-- 
markos

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

* Re: [PATCH 05/19] MIPS: asm: mips-cm: Implement mips_cm_revision
@ 2015-07-09 16:05       ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09 16:05 UTC (permalink / raw)
  To: James Hogan, linux-mips; +Cc: Paul Burton

On 07/09/2015 12:29 PM, James Hogan wrote:
> Hi Markos,
> 
> On 09/07/15 10:40, Markos Chandras wrote:
>> From: Paul Burton <paul.burton@imgtec.com>
>>
>> Provide a function to trivially return the version of the CM present in
>> the system, or 0 if no CM is present. The mips_cm_revision() will be
>> used later on to determine the CM register width, so it must not use
>> the regular CM accessors to read the revision register since that will
>> lead to build failures due to recursive inlines.
>>
>> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>>  arch/mips/include/asm/mips-cm.h | 29 +++++++++++++++++++++++++++++
>>  1 file changed, 29 insertions(+)
>>
>> diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
>> index edc7ee95269e..29ff74a629f6 100644
>> --- a/arch/mips/include/asm/mips-cm.h
>> +++ b/arch/mips/include/asm/mips-cm.h
>> @@ -189,6 +189,13 @@ BUILD_CM_Cx_R_(tcid_8_priority,	0x80)
>>  #define CM_GCR_REV_MINOR_SHF			0
>>  #define CM_GCR_REV_MINOR_MSK			(_ULCAST_(0xff) << 0)
>>  
>> +#define CM_ENCODE_REV(major, minor) \
>> +		((major << CM_GCR_REV_MAJOR_SHF) | \
>> +		 ((minor) << CM_GCR_REV_MINOR_SHF))
>> +
>> +#define CM_REV_CM2				CM_ENCODE_REV(6, 0)
>> +#define CM_REV_CM3				CM_ENCODE_REV(8, 0)
>> +
>>  /* GCR_ERROR_CAUSE register fields */
>>  #define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF		27
>>  #define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK		(_ULCAST_(0x1f) << 27)
>> @@ -324,4 +331,26 @@ static inline int mips_cm_l2sync(void)
>>  	return 0;
>>  }
>>  
>> +/**
>> + * mips_cm_revision - return CM revision
> 
> don't forget brackets: "mips_cm_revision()"
> 
>> + *
>> + * Returns the revision of the CM, from GCR_REV, or 0 if no CM is present.
>> + * The return value should be checked against the CM_REV_* macros.
> 
> Use "Return: bla bla bla." so it lands in a nice return section.
> 
> see Documentation/kernel-doc-nano-HOWTO.txt for an example.
> 
> Cheers
> James
> 
Ok thanks I will fix it.

-- 
markos

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

* Re: [PATCH 05/19] MIPS: asm: mips-cm: Implement mips_cm_revision
@ 2015-07-09 16:05       ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-09 16:05 UTC (permalink / raw)
  To: James Hogan, linux-mips; +Cc: Paul Burton

On 07/09/2015 12:29 PM, James Hogan wrote:
> Hi Markos,
> 
> On 09/07/15 10:40, Markos Chandras wrote:
>> From: Paul Burton <paul.burton@imgtec.com>
>>
>> Provide a function to trivially return the version of the CM present in
>> the system, or 0 if no CM is present. The mips_cm_revision() will be
>> used later on to determine the CM register width, so it must not use
>> the regular CM accessors to read the revision register since that will
>> lead to build failures due to recursive inlines.
>>
>> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>>  arch/mips/include/asm/mips-cm.h | 29 +++++++++++++++++++++++++++++
>>  1 file changed, 29 insertions(+)
>>
>> diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
>> index edc7ee95269e..29ff74a629f6 100644
>> --- a/arch/mips/include/asm/mips-cm.h
>> +++ b/arch/mips/include/asm/mips-cm.h
>> @@ -189,6 +189,13 @@ BUILD_CM_Cx_R_(tcid_8_priority,	0x80)
>>  #define CM_GCR_REV_MINOR_SHF			0
>>  #define CM_GCR_REV_MINOR_MSK			(_ULCAST_(0xff) << 0)
>>  
>> +#define CM_ENCODE_REV(major, minor) \
>> +		((major << CM_GCR_REV_MAJOR_SHF) | \
>> +		 ((minor) << CM_GCR_REV_MINOR_SHF))
>> +
>> +#define CM_REV_CM2				CM_ENCODE_REV(6, 0)
>> +#define CM_REV_CM3				CM_ENCODE_REV(8, 0)
>> +
>>  /* GCR_ERROR_CAUSE register fields */
>>  #define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF		27
>>  #define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK		(_ULCAST_(0x1f) << 27)
>> @@ -324,4 +331,26 @@ static inline int mips_cm_l2sync(void)
>>  	return 0;
>>  }
>>  
>> +/**
>> + * mips_cm_revision - return CM revision
> 
> don't forget brackets: "mips_cm_revision()"
> 
>> + *
>> + * Returns the revision of the CM, from GCR_REV, or 0 if no CM is present.
>> + * The return value should be checked against the CM_REV_* macros.
> 
> Use "Return: bla bla bla." so it lands in a nice return section.
> 
> see Documentation/kernel-doc-nano-HOWTO.txt for an example.
> 
> Cheers
> James
> 
Ok thanks I will fix it.

-- 
markos

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

* [PATCH v2 05/19] MIPS: asm: mips-cm: Implement mips_cm_revision
@ 2015-07-10  9:12     ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-10  9:12 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Markos Chandras

From: Paul Burton <paul.burton@imgtec.com>

Provide a function to trivially return the version of the CM present in
the system, or 0 if no CM is present. The mips_cm_revision() will be
used later on to determine the CM register width, so it must not use
the regular CM accessors to read the revision register since that will
lead to build failures due to recursive inlines.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
Changes since v1
- Fix comments to be kerneldoc friendly
- Drop static variable and add missing parens
---
 arch/mips/include/asm/mips-cm.h | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index edc7ee95269e..c70ba21e62f0 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -189,6 +189,13 @@ BUILD_CM_Cx_R_(tcid_8_priority,	0x80)
 #define CM_GCR_REV_MINOR_SHF			0
 #define CM_GCR_REV_MINOR_MSK			(_ULCAST_(0xff) << 0)
 
+#define CM_ENCODE_REV(major, minor) \
+		(((major) << CM_GCR_REV_MAJOR_SHF) | \
+		 ((minor) << CM_GCR_REV_MINOR_SHF))
+
+#define CM_REV_CM2				CM_ENCODE_REV(6, 0)
+#define CM_REV_CM3				CM_ENCODE_REV(8, 0)
+
 /* GCR_ERROR_CAUSE register fields */
 #define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF		27
 #define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK		(_ULCAST_(0x1f) << 27)
@@ -324,4 +331,18 @@ static inline int mips_cm_l2sync(void)
 	return 0;
 }
 
+/**
+ * mips_cm_revision() - return CM revision
+ *
+ * Return: The revision of the CM, from GCR_REV, or 0 if no CM is present. The
+ * return value should be checked against the CM_REV_* macros.
+ */
+static inline int mips_cm_revision(void)
+{
+	if (!mips_cm_present())
+		return 0;
+
+	return read_gcr_rev();
+}
+
 #endif /* __MIPS_ASM_MIPS_CM_H__ */
-- 
2.4.5

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

* [PATCH v2 05/19] MIPS: asm: mips-cm: Implement mips_cm_revision
@ 2015-07-10  9:12     ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-10  9:12 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Markos Chandras

From: Paul Burton <paul.burton@imgtec.com>

Provide a function to trivially return the version of the CM present in
the system, or 0 if no CM is present. The mips_cm_revision() will be
used later on to determine the CM register width, so it must not use
the regular CM accessors to read the revision register since that will
lead to build failures due to recursive inlines.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
Changes since v1
- Fix comments to be kerneldoc friendly
- Drop static variable and add missing parens
---
 arch/mips/include/asm/mips-cm.h | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index edc7ee95269e..c70ba21e62f0 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -189,6 +189,13 @@ BUILD_CM_Cx_R_(tcid_8_priority,	0x80)
 #define CM_GCR_REV_MINOR_SHF			0
 #define CM_GCR_REV_MINOR_MSK			(_ULCAST_(0xff) << 0)
 
+#define CM_ENCODE_REV(major, minor) \
+		(((major) << CM_GCR_REV_MAJOR_SHF) | \
+		 ((minor) << CM_GCR_REV_MINOR_SHF))
+
+#define CM_REV_CM2				CM_ENCODE_REV(6, 0)
+#define CM_REV_CM3				CM_ENCODE_REV(8, 0)
+
 /* GCR_ERROR_CAUSE register fields */
 #define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF		27
 #define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK		(_ULCAST_(0x1f) << 27)
@@ -324,4 +331,18 @@ static inline int mips_cm_l2sync(void)
 	return 0;
 }
 
+/**
+ * mips_cm_revision() - return CM revision
+ *
+ * Return: The revision of the CM, from GCR_REV, or 0 if no CM is present. The
+ * return value should be checked against the CM_REV_* macros.
+ */
+static inline int mips_cm_revision(void)
+{
+	if (!mips_cm_present())
+		return 0;
+
+	return read_gcr_rev();
+}
+
 #endif /* __MIPS_ASM_MIPS_CM_H__ */
-- 
2.4.5

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

* [PATCH v2 10/19] MIPS: asm: mips-cm: Extend CM accessors for 64-bit CPUs
@ 2015-07-14  8:14     ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-14  8:14 UTC (permalink / raw)
  To: linux-mips
  Cc: Markos Chandras, Thomas Gleixner, Jason Cooper, Andrew Bresticker,
	Paul Burton

Previously, the CM accessors were only accessing CM registers as u32
types instead of using the native CM register with. However, newer CMs
may actually be 64-bit on MIPS64 cores. Fortunately, current 64-bit CMs
(CM3) hold all the useful configuration bits in the lower half of the
64-bit registers (at least most of them) so they can still be accessed
using the current 32-bit accessors.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Bresticker <abrestic@chromium.org>
Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
Changes since v1
- Use 32-bit CM I/O on 32-bit kernels
---
 arch/mips/include/asm/mips-cm.h | 48 +++++++++++++++++++++++++++++++++++++----
 arch/mips/kernel/mips-cm.c      |  4 ++++
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index ca3f2c963fbd..46cc0c69b77c 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -33,6 +33,20 @@ extern void __iomem *mips_cm_l2sync_base;
  */
 extern phys_addr_t __mips_cm_phys_base(void);
 
+/*
+ * mips_cm_is64 - determine CM register width
+ *
+ * The CM register width is processor and CM specific. A 64-bit processor
+ * usually has a 64-bit CM and a 32-bit one has a 32-bit CM but a 64-bit
+ * processor could come with a 32-bit CM. Moreover, accesses on 64-bit CMs
+ * can be done either using regular 64-bit load/store instructions, or 32-bit
+ * load/store instruction on 32-bit register pairs. We opt for using 64-bit
+ * accesses on 64-bit CMs and kernels and 32-bit in any other case.
+ *
+ * It's set to 0 for 32-bit accesses and 1 for 64-bit accesses.
+ */
+extern int mips_cm_is64;
+
 /**
  * mips_cm_probe - probe for a Coherence Manager
  *
@@ -90,20 +104,46 @@ static inline bool mips_cm_has_l2sync(void)
 
 /* Macros to ease the creation of register access functions */
 #define BUILD_CM_R_(name, off)					\
-static inline u32 __iomem *addr_gcr_##name(void)		\
+static inline unsigned long __iomem *addr_gcr_##name(void)	\
 {								\
-	return (u32 __iomem *)(mips_cm_base + (off));		\
+	return (unsigned long __iomem *)(mips_cm_base + (off));	\
 }								\
 								\
-static inline u32 read_gcr_##name(void)				\
+static inline u32 read32_gcr_##name(void)			\
 {								\
 	return __raw_readl(addr_gcr_##name());			\
+}								\
+								\
+static inline u64 read64_gcr_##name(void)			\
+{								\
+	return __raw_readq(addr_gcr_##name());			\
+}								\
+								\
+static inline unsigned long read_gcr_##name(void)		\
+{								\
+	if (mips_cm_is64)					\
+		return read64_gcr_##name();			\
+	else							\
+		return read32_gcr_##name();			\
 }
 
 #define BUILD_CM__W(name, off)					\
-static inline void write_gcr_##name(u32 value)			\
+static inline void write32_gcr_##name(u32 value)		\
 {								\
 	__raw_writel(value, addr_gcr_##name());			\
+}								\
+								\
+static inline void write64_gcr_##name(u64 value)		\
+{								\
+	__raw_writeq(value, addr_gcr_##name());			\
+}								\
+								\
+static inline void write_gcr_##name(unsigned long value)	\
+{								\
+	if (mips_cm_is64)					\
+		write64_gcr_##name(value);			\
+	else							\
+		write32_gcr_##name(value);			\
 }
 
 #define BUILD_CM_RW(name, off)					\
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 42602f30949f..3d2cb6f47898 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -15,6 +15,7 @@
 
 void __iomem *mips_cm_base;
 void __iomem *mips_cm_l2sync_base;
+int mips_cm_is64;
 
 phys_addr_t __mips_cm_phys_base(void)
 {
@@ -124,5 +125,8 @@ int mips_cm_probe(void)
 	/* probe for an L2-only sync region */
 	mips_cm_probe_l2sync();
 
+	/* determine register width for this CM */
+	mips_cm_is64 = config_enabled(CONFIG_64BIT) && (mips_cm_revision() >= CM_REV_CM3);
+
 	return 0;
 }
-- 
2.4.5

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

* [PATCH v2 10/19] MIPS: asm: mips-cm: Extend CM accessors for 64-bit CPUs
@ 2015-07-14  8:14     ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-14  8:14 UTC (permalink / raw)
  To: linux-mips
  Cc: Markos Chandras, Thomas Gleixner, Jason Cooper, Andrew Bresticker,
	Paul Burton

Previously, the CM accessors were only accessing CM registers as u32
types instead of using the native CM register with. However, newer CMs
may actually be 64-bit on MIPS64 cores. Fortunately, current 64-bit CMs
(CM3) hold all the useful configuration bits in the lower half of the
64-bit registers (at least most of them) so they can still be accessed
using the current 32-bit accessors.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Bresticker <abrestic@chromium.org>
Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
Changes since v1
- Use 32-bit CM I/O on 32-bit kernels
---
 arch/mips/include/asm/mips-cm.h | 48 +++++++++++++++++++++++++++++++++++++----
 arch/mips/kernel/mips-cm.c      |  4 ++++
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index ca3f2c963fbd..46cc0c69b77c 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -33,6 +33,20 @@ extern void __iomem *mips_cm_l2sync_base;
  */
 extern phys_addr_t __mips_cm_phys_base(void);
 
+/*
+ * mips_cm_is64 - determine CM register width
+ *
+ * The CM register width is processor and CM specific. A 64-bit processor
+ * usually has a 64-bit CM and a 32-bit one has a 32-bit CM but a 64-bit
+ * processor could come with a 32-bit CM. Moreover, accesses on 64-bit CMs
+ * can be done either using regular 64-bit load/store instructions, or 32-bit
+ * load/store instruction on 32-bit register pairs. We opt for using 64-bit
+ * accesses on 64-bit CMs and kernels and 32-bit in any other case.
+ *
+ * It's set to 0 for 32-bit accesses and 1 for 64-bit accesses.
+ */
+extern int mips_cm_is64;
+
 /**
  * mips_cm_probe - probe for a Coherence Manager
  *
@@ -90,20 +104,46 @@ static inline bool mips_cm_has_l2sync(void)
 
 /* Macros to ease the creation of register access functions */
 #define BUILD_CM_R_(name, off)					\
-static inline u32 __iomem *addr_gcr_##name(void)		\
+static inline unsigned long __iomem *addr_gcr_##name(void)	\
 {								\
-	return (u32 __iomem *)(mips_cm_base + (off));		\
+	return (unsigned long __iomem *)(mips_cm_base + (off));	\
 }								\
 								\
-static inline u32 read_gcr_##name(void)				\
+static inline u32 read32_gcr_##name(void)			\
 {								\
 	return __raw_readl(addr_gcr_##name());			\
+}								\
+								\
+static inline u64 read64_gcr_##name(void)			\
+{								\
+	return __raw_readq(addr_gcr_##name());			\
+}								\
+								\
+static inline unsigned long read_gcr_##name(void)		\
+{								\
+	if (mips_cm_is64)					\
+		return read64_gcr_##name();			\
+	else							\
+		return read32_gcr_##name();			\
 }
 
 #define BUILD_CM__W(name, off)					\
-static inline void write_gcr_##name(u32 value)			\
+static inline void write32_gcr_##name(u32 value)		\
 {								\
 	__raw_writel(value, addr_gcr_##name());			\
+}								\
+								\
+static inline void write64_gcr_##name(u64 value)		\
+{								\
+	__raw_writeq(value, addr_gcr_##name());			\
+}								\
+								\
+static inline void write_gcr_##name(unsigned long value)	\
+{								\
+	if (mips_cm_is64)					\
+		write64_gcr_##name(value);			\
+	else							\
+		write32_gcr_##name(value);			\
 }
 
 #define BUILD_CM_RW(name, off)					\
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 42602f30949f..3d2cb6f47898 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -15,6 +15,7 @@
 
 void __iomem *mips_cm_base;
 void __iomem *mips_cm_l2sync_base;
+int mips_cm_is64;
 
 phys_addr_t __mips_cm_phys_base(void)
 {
@@ -124,5 +125,8 @@ int mips_cm_probe(void)
 	/* probe for an L2-only sync region */
 	mips_cm_probe_l2sync();
 
+	/* determine register width for this CM */
+	mips_cm_is64 = config_enabled(CONFIG_64BIT) && (mips_cm_revision() >= CM_REV_CM3);
+
 	return 0;
 }
-- 
2.4.5

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

* Re: [PATCH v2 10/19] MIPS: asm: mips-cm: Extend CM accessors for 64-bit CPUs
@ 2015-07-14  8:30       ` Paul Burton
  0 siblings, 0 replies; 65+ messages in thread
From: Paul Burton @ 2015-07-14  8:30 UTC (permalink / raw)
  To: Markos Chandras
  Cc: linux-mips, Thomas Gleixner, Jason Cooper, Andrew Bresticker

On Tue, Jul 14, 2015 at 09:14:12AM +0100, Markos Chandras wrote:
> Previously, the CM accessors were only accessing CM registers as u32
> types instead of using the native CM register with. However, newer CMs
> may actually be 64-bit on MIPS64 cores. Fortunately, current 64-bit CMs
> (CM3) hold all the useful configuration bits in the lower half of the
> 64-bit registers (at least most of them) so they can still be accessed
> using the current 32-bit accessors.
> 
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Jason Cooper <jason@lakedaemon.net>
> Cc: Andrew Bresticker <abrestic@chromium.org>
> Cc: Paul Burton <paul.burton@imgtec.com>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
> Changes since v1
> - Use 32-bit CM I/O on 32-bit kernels

A concern I have, but haven't yet drank enough coffee to think through
fully, is whether this will work on big endian systems. These are 64b
addresses and you're writing 32b to their addresses which I suspect may
go horribly wrong.

Thanks,
    Paul

> ---
>  arch/mips/include/asm/mips-cm.h | 48 +++++++++++++++++++++++++++++++++++++----
>  arch/mips/kernel/mips-cm.c      |  4 ++++
>  2 files changed, 48 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
> index ca3f2c963fbd..46cc0c69b77c 100644
> --- a/arch/mips/include/asm/mips-cm.h
> +++ b/arch/mips/include/asm/mips-cm.h
> @@ -33,6 +33,20 @@ extern void __iomem *mips_cm_l2sync_base;
>   */
>  extern phys_addr_t __mips_cm_phys_base(void);
>  
> +/*
> + * mips_cm_is64 - determine CM register width
> + *
> + * The CM register width is processor and CM specific. A 64-bit processor
> + * usually has a 64-bit CM and a 32-bit one has a 32-bit CM but a 64-bit
> + * processor could come with a 32-bit CM. Moreover, accesses on 64-bit CMs
> + * can be done either using regular 64-bit load/store instructions, or 32-bit
> + * load/store instruction on 32-bit register pairs. We opt for using 64-bit
> + * accesses on 64-bit CMs and kernels and 32-bit in any other case.
> + *
> + * It's set to 0 for 32-bit accesses and 1 for 64-bit accesses.
> + */
> +extern int mips_cm_is64;
> +
>  /**
>   * mips_cm_probe - probe for a Coherence Manager
>   *
> @@ -90,20 +104,46 @@ static inline bool mips_cm_has_l2sync(void)
>  
>  /* Macros to ease the creation of register access functions */
>  #define BUILD_CM_R_(name, off)					\
> -static inline u32 __iomem *addr_gcr_##name(void)		\
> +static inline unsigned long __iomem *addr_gcr_##name(void)	\
>  {								\
> -	return (u32 __iomem *)(mips_cm_base + (off));		\
> +	return (unsigned long __iomem *)(mips_cm_base + (off));	\
>  }								\
>  								\
> -static inline u32 read_gcr_##name(void)				\
> +static inline u32 read32_gcr_##name(void)			\
>  {								\
>  	return __raw_readl(addr_gcr_##name());			\
> +}								\
> +								\
> +static inline u64 read64_gcr_##name(void)			\
> +{								\
> +	return __raw_readq(addr_gcr_##name());			\
> +}								\
> +								\
> +static inline unsigned long read_gcr_##name(void)		\
> +{								\
> +	if (mips_cm_is64)					\
> +		return read64_gcr_##name();			\
> +	else							\
> +		return read32_gcr_##name();			\
>  }
>  
>  #define BUILD_CM__W(name, off)					\
> -static inline void write_gcr_##name(u32 value)			\
> +static inline void write32_gcr_##name(u32 value)		\
>  {								\
>  	__raw_writel(value, addr_gcr_##name());			\
> +}								\
> +								\
> +static inline void write64_gcr_##name(u64 value)		\
> +{								\
> +	__raw_writeq(value, addr_gcr_##name());			\
> +}								\
> +								\
> +static inline void write_gcr_##name(unsigned long value)	\
> +{								\
> +	if (mips_cm_is64)					\
> +		write64_gcr_##name(value);			\
> +	else							\
> +		write32_gcr_##name(value);			\
>  }
>  
>  #define BUILD_CM_RW(name, off)					\
> diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
> index 42602f30949f..3d2cb6f47898 100644
> --- a/arch/mips/kernel/mips-cm.c
> +++ b/arch/mips/kernel/mips-cm.c
> @@ -15,6 +15,7 @@
>  
>  void __iomem *mips_cm_base;
>  void __iomem *mips_cm_l2sync_base;
> +int mips_cm_is64;
>  
>  phys_addr_t __mips_cm_phys_base(void)
>  {
> @@ -124,5 +125,8 @@ int mips_cm_probe(void)
>  	/* probe for an L2-only sync region */
>  	mips_cm_probe_l2sync();
>  
> +	/* determine register width for this CM */
> +	mips_cm_is64 = config_enabled(CONFIG_64BIT) && (mips_cm_revision() >= CM_REV_CM3);
> +
>  	return 0;
>  }
> -- 
> 2.4.5
> 

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

* Re: [PATCH v2 10/19] MIPS: asm: mips-cm: Extend CM accessors for 64-bit CPUs
@ 2015-07-14  8:30       ` Paul Burton
  0 siblings, 0 replies; 65+ messages in thread
From: Paul Burton @ 2015-07-14  8:30 UTC (permalink / raw)
  To: Markos Chandras
  Cc: linux-mips, Thomas Gleixner, Jason Cooper, Andrew Bresticker

On Tue, Jul 14, 2015 at 09:14:12AM +0100, Markos Chandras wrote:
> Previously, the CM accessors were only accessing CM registers as u32
> types instead of using the native CM register with. However, newer CMs
> may actually be 64-bit on MIPS64 cores. Fortunately, current 64-bit CMs
> (CM3) hold all the useful configuration bits in the lower half of the
> 64-bit registers (at least most of them) so they can still be accessed
> using the current 32-bit accessors.
> 
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Jason Cooper <jason@lakedaemon.net>
> Cc: Andrew Bresticker <abrestic@chromium.org>
> Cc: Paul Burton <paul.burton@imgtec.com>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
> Changes since v1
> - Use 32-bit CM I/O on 32-bit kernels

A concern I have, but haven't yet drank enough coffee to think through
fully, is whether this will work on big endian systems. These are 64b
addresses and you're writing 32b to their addresses which I suspect may
go horribly wrong.

Thanks,
    Paul

> ---
>  arch/mips/include/asm/mips-cm.h | 48 +++++++++++++++++++++++++++++++++++++----
>  arch/mips/kernel/mips-cm.c      |  4 ++++
>  2 files changed, 48 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
> index ca3f2c963fbd..46cc0c69b77c 100644
> --- a/arch/mips/include/asm/mips-cm.h
> +++ b/arch/mips/include/asm/mips-cm.h
> @@ -33,6 +33,20 @@ extern void __iomem *mips_cm_l2sync_base;
>   */
>  extern phys_addr_t __mips_cm_phys_base(void);
>  
> +/*
> + * mips_cm_is64 - determine CM register width
> + *
> + * The CM register width is processor and CM specific. A 64-bit processor
> + * usually has a 64-bit CM and a 32-bit one has a 32-bit CM but a 64-bit
> + * processor could come with a 32-bit CM. Moreover, accesses on 64-bit CMs
> + * can be done either using regular 64-bit load/store instructions, or 32-bit
> + * load/store instruction on 32-bit register pairs. We opt for using 64-bit
> + * accesses on 64-bit CMs and kernels and 32-bit in any other case.
> + *
> + * It's set to 0 for 32-bit accesses and 1 for 64-bit accesses.
> + */
> +extern int mips_cm_is64;
> +
>  /**
>   * mips_cm_probe - probe for a Coherence Manager
>   *
> @@ -90,20 +104,46 @@ static inline bool mips_cm_has_l2sync(void)
>  
>  /* Macros to ease the creation of register access functions */
>  #define BUILD_CM_R_(name, off)					\
> -static inline u32 __iomem *addr_gcr_##name(void)		\
> +static inline unsigned long __iomem *addr_gcr_##name(void)	\
>  {								\
> -	return (u32 __iomem *)(mips_cm_base + (off));		\
> +	return (unsigned long __iomem *)(mips_cm_base + (off));	\
>  }								\
>  								\
> -static inline u32 read_gcr_##name(void)				\
> +static inline u32 read32_gcr_##name(void)			\
>  {								\
>  	return __raw_readl(addr_gcr_##name());			\
> +}								\
> +								\
> +static inline u64 read64_gcr_##name(void)			\
> +{								\
> +	return __raw_readq(addr_gcr_##name());			\
> +}								\
> +								\
> +static inline unsigned long read_gcr_##name(void)		\
> +{								\
> +	if (mips_cm_is64)					\
> +		return read64_gcr_##name();			\
> +	else							\
> +		return read32_gcr_##name();			\
>  }
>  
>  #define BUILD_CM__W(name, off)					\
> -static inline void write_gcr_##name(u32 value)			\
> +static inline void write32_gcr_##name(u32 value)		\
>  {								\
>  	__raw_writel(value, addr_gcr_##name());			\
> +}								\
> +								\
> +static inline void write64_gcr_##name(u64 value)		\
> +{								\
> +	__raw_writeq(value, addr_gcr_##name());			\
> +}								\
> +								\
> +static inline void write_gcr_##name(unsigned long value)	\
> +{								\
> +	if (mips_cm_is64)					\
> +		write64_gcr_##name(value);			\
> +	else							\
> +		write32_gcr_##name(value);			\
>  }
>  
>  #define BUILD_CM_RW(name, off)					\
> diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
> index 42602f30949f..3d2cb6f47898 100644
> --- a/arch/mips/kernel/mips-cm.c
> +++ b/arch/mips/kernel/mips-cm.c
> @@ -15,6 +15,7 @@
>  
>  void __iomem *mips_cm_base;
>  void __iomem *mips_cm_l2sync_base;
> +int mips_cm_is64;
>  
>  phys_addr_t __mips_cm_phys_base(void)
>  {
> @@ -124,5 +125,8 @@ int mips_cm_probe(void)
>  	/* probe for an L2-only sync region */
>  	mips_cm_probe_l2sync();
>  
> +	/* determine register width for this CM */
> +	mips_cm_is64 = config_enabled(CONFIG_64BIT) && (mips_cm_revision() >= CM_REV_CM3);
> +
>  	return 0;
>  }
> -- 
> 2.4.5
> 

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

* Re: [PATCH v2 10/19] MIPS: asm: mips-cm: Extend CM accessors for 64-bit CPUs
@ 2015-07-14  8:35         ` Paul Burton
  0 siblings, 0 replies; 65+ messages in thread
From: Paul Burton @ 2015-07-14  8:35 UTC (permalink / raw)
  To: Markos Chandras
  Cc: linux-mips, Thomas Gleixner, Jason Cooper, Andrew Bresticker

On Tue, Jul 14, 2015 at 09:30:19AM +0100, Paul Burton wrote:
> On Tue, Jul 14, 2015 at 09:14:12AM +0100, Markos Chandras wrote:
> > Previously, the CM accessors were only accessing CM registers as u32
> > types instead of using the native CM register with. However, newer CMs
> > may actually be 64-bit on MIPS64 cores. Fortunately, current 64-bit CMs
> > (CM3) hold all the useful configuration bits in the lower half of the
> > 64-bit registers (at least most of them) so they can still be accessed
> > using the current 32-bit accessors.
> > 
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Cc: Jason Cooper <jason@lakedaemon.net>
> > Cc: Andrew Bresticker <abrestic@chromium.org>
> > Cc: Paul Burton <paul.burton@imgtec.com>
> > Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> > ---
> > Changes since v1
> > - Use 32-bit CM I/O on 32-bit kernels
> 
> A concern I have, but haven't yet drank enough coffee to think through
> fully, is whether this will work on big endian systems. These are 64b
> addresses and you're writing 32b to their addresses which I suspect may
> go horribly wrong.

Should be:

"These are 64b registers and you're writing 32b to their addresses"

Apparently I haven't drunk enouugh coffee to formulate sentences yet
either ;)

Thanks,
    Paul

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

* Re: [PATCH v2 10/19] MIPS: asm: mips-cm: Extend CM accessors for 64-bit CPUs
@ 2015-07-14  8:35         ` Paul Burton
  0 siblings, 0 replies; 65+ messages in thread
From: Paul Burton @ 2015-07-14  8:35 UTC (permalink / raw)
  To: Markos Chandras
  Cc: linux-mips, Thomas Gleixner, Jason Cooper, Andrew Bresticker

On Tue, Jul 14, 2015 at 09:30:19AM +0100, Paul Burton wrote:
> On Tue, Jul 14, 2015 at 09:14:12AM +0100, Markos Chandras wrote:
> > Previously, the CM accessors were only accessing CM registers as u32
> > types instead of using the native CM register with. However, newer CMs
> > may actually be 64-bit on MIPS64 cores. Fortunately, current 64-bit CMs
> > (CM3) hold all the useful configuration bits in the lower half of the
> > 64-bit registers (at least most of them) so they can still be accessed
> > using the current 32-bit accessors.
> > 
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Cc: Jason Cooper <jason@lakedaemon.net>
> > Cc: Andrew Bresticker <abrestic@chromium.org>
> > Cc: Paul Burton <paul.burton@imgtec.com>
> > Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> > ---
> > Changes since v1
> > - Use 32-bit CM I/O on 32-bit kernels
> 
> A concern I have, but haven't yet drank enough coffee to think through
> fully, is whether this will work on big endian systems. These are 64b
> addresses and you're writing 32b to their addresses which I suspect may
> go horribly wrong.

Should be:

"These are 64b registers and you're writing 32b to their addresses"

Apparently I haven't drunk enouugh coffee to formulate sentences yet
either ;)

Thanks,
    Paul

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

* Re: [PATCH v2 10/19] MIPS: asm: mips-cm: Extend CM accessors for 64-bit CPUs
@ 2015-07-14  8:45           ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-14  8:45 UTC (permalink / raw)
  To: Paul Burton; +Cc: linux-mips, Thomas Gleixner, Jason Cooper, Andrew Bresticker

On 07/14/2015 09:35 AM, Paul Burton wrote:
> On Tue, Jul 14, 2015 at 09:30:19AM +0100, Paul Burton wrote:
>> On Tue, Jul 14, 2015 at 09:14:12AM +0100, Markos Chandras wrote:
>>> Previously, the CM accessors were only accessing CM registers as u32
>>> types instead of using the native CM register with. However, newer CMs
>>> may actually be 64-bit on MIPS64 cores. Fortunately, current 64-bit CMs
>>> (CM3) hold all the useful configuration bits in the lower half of the
>>> 64-bit registers (at least most of them) so they can still be accessed
>>> using the current 32-bit accessors.
>>>
>>> Cc: Thomas Gleixner <tglx@linutronix.de>
>>> Cc: Jason Cooper <jason@lakedaemon.net>
>>> Cc: Andrew Bresticker <abrestic@chromium.org>
>>> Cc: Paul Burton <paul.burton@imgtec.com>
>>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>>> ---
>>> Changes since v1
>>> - Use 32-bit CM I/O on 32-bit kernels
>>
>> A concern I have, but haven't yet drank enough coffee to think through
>> fully, is whether this will work on big endian systems. These are 64b
>> addresses and you're writing 32b to their addresses which I suspect may
>> go horribly wrong.
> 
> Should be:
> 
> "These are 64b registers and you're writing 32b to their addresses"
> 
> Apparently I haven't drunk enouugh coffee to formulate sentences yet
> either ;)
> 
> Thanks,
>     Paul
> 

The HW team told me that the CM regs can be accessed in LE-pair format
even on big-endian cores in the sense that bit0 of a 64-bit CM reg will
always be on the lower address. I have never tested that really.

-- 
markos

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

* Re: [PATCH v2 10/19] MIPS: asm: mips-cm: Extend CM accessors for 64-bit CPUs
@ 2015-07-14  8:45           ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-14  8:45 UTC (permalink / raw)
  To: Paul Burton; +Cc: linux-mips, Thomas Gleixner, Jason Cooper, Andrew Bresticker

On 07/14/2015 09:35 AM, Paul Burton wrote:
> On Tue, Jul 14, 2015 at 09:30:19AM +0100, Paul Burton wrote:
>> On Tue, Jul 14, 2015 at 09:14:12AM +0100, Markos Chandras wrote:
>>> Previously, the CM accessors were only accessing CM registers as u32
>>> types instead of using the native CM register with. However, newer CMs
>>> may actually be 64-bit on MIPS64 cores. Fortunately, current 64-bit CMs
>>> (CM3) hold all the useful configuration bits in the lower half of the
>>> 64-bit registers (at least most of them) so they can still be accessed
>>> using the current 32-bit accessors.
>>>
>>> Cc: Thomas Gleixner <tglx@linutronix.de>
>>> Cc: Jason Cooper <jason@lakedaemon.net>
>>> Cc: Andrew Bresticker <abrestic@chromium.org>
>>> Cc: Paul Burton <paul.burton@imgtec.com>
>>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>>> ---
>>> Changes since v1
>>> - Use 32-bit CM I/O on 32-bit kernels
>>
>> A concern I have, but haven't yet drank enough coffee to think through
>> fully, is whether this will work on big endian systems. These are 64b
>> addresses and you're writing 32b to their addresses which I suspect may
>> go horribly wrong.
> 
> Should be:
> 
> "These are 64b registers and you're writing 32b to their addresses"
> 
> Apparently I haven't drunk enouugh coffee to formulate sentences yet
> either ;)
> 
> Thanks,
>     Paul
> 

The HW team told me that the CM regs can be accessed in LE-pair format
even on big-endian cores in the sense that bit0 of a 64-bit CM reg will
always be on the lower address. I have never tested that really.

-- 
markos

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

* [PATCH v2 14/19] drivers: irqchip: irq-mips-gic: Extend GIC accessors for 64-bit CMs
@ 2015-07-14  9:26     ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-14  9:26 UTC (permalink / raw)
  To: linux-mips
  Cc: Markos Chandras, Thomas Gleixner, Jason Cooper, Andrew Bresticker,
	Paul Burton

Previously, the GIC accessors were only accessing u32 registers but
newer CMs may actually be 64-bit on MIPS64 cores. As a result of which,
extended these accessors to support 64-bit reads and writes.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Bresticker <abrestic@chromium.org>
Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
Changes since v1:
- Use 32-bit I/O for VPE_{OTHER,LOCAL} RMASK register
---
 drivers/irqchip/irq-mips-gic.c   | 121 ++++++++++++++++++++++++---------------
 include/linux/irqchip/mips-gic.h |  10 +++-
 2 files changed, 84 insertions(+), 47 deletions(-)

diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 4400edd1a6c7..aa4ef46ee196 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -42,20 +42,46 @@ static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller;
 
 static void __gic_irq_dispatch(void);
 
-static inline unsigned int gic_read(unsigned int reg)
+static inline u32 gic_read32(unsigned int reg)
 {
 	return __raw_readl(gic_base + reg);
 }
 
-static inline void gic_write(unsigned int reg, unsigned int val)
+static inline u64 gic_read64(unsigned int reg)
 {
-	__raw_writel(val, gic_base + reg);
+	return __raw_readq(gic_base + reg);
 }
 
-static inline void gic_update_bits(unsigned int reg, unsigned int mask,
-				   unsigned int val)
+static inline unsigned long gic_read(unsigned int reg)
 {
-	unsigned int regval;
+	if (!mips_cm_is64)
+		return gic_read32(reg);
+	else
+		return gic_read64(reg);
+}
+
+static inline void gic_write32(unsigned int reg, u32 val)
+{
+	return __raw_writel(val, gic_base + reg);
+}
+
+static inline void gic_write64(unsigned int reg, u64 val)
+{
+	return __raw_writeq(val, gic_base + reg);
+}
+
+static inline void gic_write(unsigned int reg, unsigned long val)
+{
+	if (!mips_cm_is64)
+		return gic_write32(reg, (u32)val);
+	else
+		return gic_write64(reg, (u64)val);
+}
+
+static inline void gic_update_bits(unsigned int reg, unsigned long mask,
+				   unsigned long val)
+{
+	unsigned long regval;
 
 	regval = gic_read(reg);
 	regval &= ~mask;
@@ -66,40 +92,40 @@ static inline void gic_update_bits(unsigned int reg, unsigned int mask,
 static inline void gic_reset_mask(unsigned int intr)
 {
 	gic_write(GIC_REG(SHARED, GIC_SH_RMASK) + GIC_INTR_OFS(intr),
-		  1 << GIC_INTR_BIT(intr));
+		  1ul << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_mask(unsigned int intr)
 {
 	gic_write(GIC_REG(SHARED, GIC_SH_SMASK) + GIC_INTR_OFS(intr),
-		  1 << GIC_INTR_BIT(intr));
+		  1ul << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_polarity(unsigned int intr, unsigned int pol)
 {
 	gic_update_bits(GIC_REG(SHARED, GIC_SH_SET_POLARITY) +
-			GIC_INTR_OFS(intr), 1 << GIC_INTR_BIT(intr),
-			pol << GIC_INTR_BIT(intr));
+			GIC_INTR_OFS(intr), 1ul << GIC_INTR_BIT(intr),
+			(unsigned long)pol << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_trigger(unsigned int intr, unsigned int trig)
 {
 	gic_update_bits(GIC_REG(SHARED, GIC_SH_SET_TRIGGER) +
-			GIC_INTR_OFS(intr), 1 << GIC_INTR_BIT(intr),
-			trig << GIC_INTR_BIT(intr));
+			GIC_INTR_OFS(intr), 1ul << GIC_INTR_BIT(intr),
+			(unsigned long)trig << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_dual_edge(unsigned int intr, unsigned int dual)
 {
 	gic_update_bits(GIC_REG(SHARED, GIC_SH_SET_DUAL) + GIC_INTR_OFS(intr),
-			1 << GIC_INTR_BIT(intr),
-			dual << GIC_INTR_BIT(intr));
+			1ul << GIC_INTR_BIT(intr),
+			(unsigned long)dual << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_map_to_pin(unsigned int intr, unsigned int pin)
 {
-	gic_write(GIC_REG(SHARED, GIC_SH_INTR_MAP_TO_PIN_BASE) +
-		  GIC_SH_MAP_TO_PIN(intr), GIC_MAP_TO_PIN_MSK | pin);
+	gic_write32(GIC_REG(SHARED, GIC_SH_INTR_MAP_TO_PIN_BASE) +
+		    GIC_SH_MAP_TO_PIN(intr), GIC_MAP_TO_PIN_MSK | pin);
 }
 
 static inline void gic_map_to_vpe(unsigned int intr, unsigned int vpe)
@@ -115,9 +141,9 @@ cycle_t gic_read_count(void)
 	unsigned int hi, hi2, lo;
 
 	do {
-		hi = gic_read(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
-		lo = gic_read(GIC_REG(SHARED, GIC_SH_COUNTER_31_00));
-		hi2 = gic_read(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
+		hi = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
+		lo = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_31_00));
+		hi2 = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
 	} while (hi2 != hi);
 
 	return (((cycle_t) hi) << 32) + lo;
@@ -136,9 +162,9 @@ unsigned int gic_get_count_width(void)
 
 void gic_write_compare(cycle_t cnt)
 {
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
 				(int)(cnt >> 32));
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
 				(int)(cnt & 0xffffffff));
 }
 
@@ -148,10 +174,10 @@ void gic_write_cpu_compare(cycle_t cnt, int cpu)
 
 	local_irq_save(flags);
 
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
-	gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
+	gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
 				(int)(cnt >> 32));
-	gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
+	gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
 				(int)(cnt & 0xffffffff));
 
 	local_irq_restore(flags);
@@ -161,8 +187,8 @@ cycle_t gic_read_compare(void)
 {
 	unsigned int hi, lo;
 
-	hi = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI));
-	lo = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO));
+	hi = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI));
+	lo = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO));
 
 	return (((cycle_t) hi) << 32) + lo;
 }
@@ -197,7 +223,7 @@ static bool gic_local_irq_is_routable(int intr)
 	if (cpu_has_veic)
 		return true;
 
-	vpe_ctl = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_CTL));
+	vpe_ctl = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_CTL));
 	switch (intr) {
 	case GIC_LOCAL_INT_TIMER:
 		return vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK;
@@ -273,7 +299,7 @@ int gic_get_c0_fdc_int(void)
 
 static void gic_handle_shared_int(bool chained)
 {
-	unsigned int i, intr, virq;
+	unsigned int i, intr, virq, gic_reg_step = mips_cm_is64 ? 8 : 4;
 	unsigned long *pcpu_mask;
 	unsigned long pending_reg, intrmask_reg;
 	DECLARE_BITMAP(pending, GIC_MAX_INTRS);
@@ -288,8 +314,8 @@ static void gic_handle_shared_int(bool chained)
 	for (i = 0; i < BITS_TO_LONGS(gic_shared_intrs); i++) {
 		pending[i] = gic_read(pending_reg);
 		intrmask[i] = gic_read(intrmask_reg);
-		pending_reg += 0x4;
-		intrmask_reg += 0x4;
+		pending_reg += gic_reg_step;
+		intrmask_reg += gic_reg_step;
 	}
 
 	bitmap_and(pending, pending, intrmask, gic_shared_intrs);
@@ -439,8 +465,8 @@ static void gic_handle_local_int(bool chained)
 	unsigned long pending, masked;
 	unsigned int intr, virq;
 
-	pending = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_PEND));
-	masked = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_MASK));
+	pending = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_PEND));
+	masked = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_MASK));
 
 	bitmap_and(&pending, &pending, &masked, GIC_NUM_LOCAL_INTRS);
 
@@ -463,14 +489,14 @@ static void gic_mask_local_irq(struct irq_data *d)
 {
 	int intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
 
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_RMASK), 1 << intr);
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_RMASK), 1 << intr);
 }
 
 static void gic_unmask_local_irq(struct irq_data *d)
 {
 	int intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
 
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), 1 << intr);
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), 1 << intr);
 }
 
 static struct irq_chip gic_local_irq_controller = {
@@ -488,7 +514,7 @@ static void gic_mask_local_irq_all_vpes(struct irq_data *d)
 	spin_lock_irqsave(&gic_lock, flags);
 	for (i = 0; i < gic_vpes; i++) {
 		gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
-		gic_write(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << intr);
+		gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << intr);
 	}
 	spin_unlock_irqrestore(&gic_lock, flags);
 }
@@ -502,7 +528,7 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
 	spin_lock_irqsave(&gic_lock, flags);
 	for (i = 0; i < gic_vpes; i++) {
 		gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
-		gic_write(GIC_REG(VPE_OTHER, GIC_VPE_SMASK), 1 << intr);
+		gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SMASK), 1 << intr);
 	}
 	spin_unlock_irqrestore(&gic_lock, flags);
 }
@@ -622,7 +648,7 @@ static void __init gic_basic_init(void)
 		for (j = 0; j < GIC_NUM_LOCAL_INTRS; j++) {
 			if (!gic_local_irq_is_routable(j))
 				continue;
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << j);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << j);
 		}
 	}
 }
@@ -667,27 +693,32 @@ static int gic_local_irq_domain_map(struct irq_domain *d, unsigned int virq,
 
 		switch (intr) {
 		case GIC_LOCAL_INT_WD:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_WD_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_WD_MAP), val);
 			break;
 		case GIC_LOCAL_INT_COMPARE:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_TIMER:
 			/* CONFIG_MIPS_CMP workaround (see __gic_init) */
 			val = GIC_MAP_TO_PIN_MSK | timer_cpu_pin;
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_PERFCTR:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_SWINT0:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_SWINT0_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SWINT0_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_SWINT1:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_SWINT1_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SWINT1_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_FDC:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_FDC_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_FDC_MAP), val);
 			break;
 		default:
 			pr_err("Invalid local IRQ %d\n", intr);
@@ -792,7 +823,7 @@ static void __init __gic_init(unsigned long gic_base_addr,
 		 */
 		if (IS_ENABLED(CONFIG_MIPS_CMP) &&
 		    gic_local_irq_is_routable(GIC_LOCAL_INT_TIMER)) {
-			timer_cpu_pin = gic_read(GIC_REG(VPE_LOCAL,
+			timer_cpu_pin = gic_read32(GIC_REG(VPE_LOCAL,
 							 GIC_VPE_TIMER_MAP)) &
 					GIC_MAP_MSK;
 			irq_set_chained_handler(MIPS_CPU_IRQ_BASE +
diff --git a/include/linux/irqchip/mips-gic.h b/include/linux/irqchip/mips-gic.h
index 9b1ad3734911..10e4a9073019 100644
--- a/include/linux/irqchip/mips-gic.h
+++ b/include/linux/irqchip/mips-gic.h
@@ -45,8 +45,14 @@
 #define GIC_SH_REVISIONID_OFS		0x0020
 
 /* Convert an interrupt number to a byte offset/bit for multi-word registers */
-#define GIC_INTR_OFS(intr)		(((intr) / 32) * 4)
-#define GIC_INTR_BIT(intr)		((intr) % 32)
+#define GIC_INTR_OFS(intr) ({				\
+	unsigned bits = mips_cm_is64 ? 64 : 32;		\
+	unsigned reg_idx = (intr) / bits;		\
+	unsigned reg_width = bits / 8;			\
+							\
+	reg_idx * reg_width;				\
+})
+#define GIC_INTR_BIT(intr)		((intr) % (mips_cm_is64 ? 64 : 32))
 
 /* Polarity : Reset Value is always 0 */
 #define GIC_SH_SET_POLARITY_OFS		0x0100
-- 
2.4.5

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

* [PATCH v2 14/19] drivers: irqchip: irq-mips-gic: Extend GIC accessors for 64-bit CMs
@ 2015-07-14  9:26     ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-14  9:26 UTC (permalink / raw)
  To: linux-mips
  Cc: Markos Chandras, Thomas Gleixner, Jason Cooper, Andrew Bresticker,
	Paul Burton

Previously, the GIC accessors were only accessing u32 registers but
newer CMs may actually be 64-bit on MIPS64 cores. As a result of which,
extended these accessors to support 64-bit reads and writes.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Bresticker <abrestic@chromium.org>
Cc: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
Changes since v1:
- Use 32-bit I/O for VPE_{OTHER,LOCAL} RMASK register
---
 drivers/irqchip/irq-mips-gic.c   | 121 ++++++++++++++++++++++++---------------
 include/linux/irqchip/mips-gic.h |  10 +++-
 2 files changed, 84 insertions(+), 47 deletions(-)

diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 4400edd1a6c7..aa4ef46ee196 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -42,20 +42,46 @@ static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller;
 
 static void __gic_irq_dispatch(void);
 
-static inline unsigned int gic_read(unsigned int reg)
+static inline u32 gic_read32(unsigned int reg)
 {
 	return __raw_readl(gic_base + reg);
 }
 
-static inline void gic_write(unsigned int reg, unsigned int val)
+static inline u64 gic_read64(unsigned int reg)
 {
-	__raw_writel(val, gic_base + reg);
+	return __raw_readq(gic_base + reg);
 }
 
-static inline void gic_update_bits(unsigned int reg, unsigned int mask,
-				   unsigned int val)
+static inline unsigned long gic_read(unsigned int reg)
 {
-	unsigned int regval;
+	if (!mips_cm_is64)
+		return gic_read32(reg);
+	else
+		return gic_read64(reg);
+}
+
+static inline void gic_write32(unsigned int reg, u32 val)
+{
+	return __raw_writel(val, gic_base + reg);
+}
+
+static inline void gic_write64(unsigned int reg, u64 val)
+{
+	return __raw_writeq(val, gic_base + reg);
+}
+
+static inline void gic_write(unsigned int reg, unsigned long val)
+{
+	if (!mips_cm_is64)
+		return gic_write32(reg, (u32)val);
+	else
+		return gic_write64(reg, (u64)val);
+}
+
+static inline void gic_update_bits(unsigned int reg, unsigned long mask,
+				   unsigned long val)
+{
+	unsigned long regval;
 
 	regval = gic_read(reg);
 	regval &= ~mask;
@@ -66,40 +92,40 @@ static inline void gic_update_bits(unsigned int reg, unsigned int mask,
 static inline void gic_reset_mask(unsigned int intr)
 {
 	gic_write(GIC_REG(SHARED, GIC_SH_RMASK) + GIC_INTR_OFS(intr),
-		  1 << GIC_INTR_BIT(intr));
+		  1ul << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_mask(unsigned int intr)
 {
 	gic_write(GIC_REG(SHARED, GIC_SH_SMASK) + GIC_INTR_OFS(intr),
-		  1 << GIC_INTR_BIT(intr));
+		  1ul << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_polarity(unsigned int intr, unsigned int pol)
 {
 	gic_update_bits(GIC_REG(SHARED, GIC_SH_SET_POLARITY) +
-			GIC_INTR_OFS(intr), 1 << GIC_INTR_BIT(intr),
-			pol << GIC_INTR_BIT(intr));
+			GIC_INTR_OFS(intr), 1ul << GIC_INTR_BIT(intr),
+			(unsigned long)pol << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_trigger(unsigned int intr, unsigned int trig)
 {
 	gic_update_bits(GIC_REG(SHARED, GIC_SH_SET_TRIGGER) +
-			GIC_INTR_OFS(intr), 1 << GIC_INTR_BIT(intr),
-			trig << GIC_INTR_BIT(intr));
+			GIC_INTR_OFS(intr), 1ul << GIC_INTR_BIT(intr),
+			(unsigned long)trig << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_set_dual_edge(unsigned int intr, unsigned int dual)
 {
 	gic_update_bits(GIC_REG(SHARED, GIC_SH_SET_DUAL) + GIC_INTR_OFS(intr),
-			1 << GIC_INTR_BIT(intr),
-			dual << GIC_INTR_BIT(intr));
+			1ul << GIC_INTR_BIT(intr),
+			(unsigned long)dual << GIC_INTR_BIT(intr));
 }
 
 static inline void gic_map_to_pin(unsigned int intr, unsigned int pin)
 {
-	gic_write(GIC_REG(SHARED, GIC_SH_INTR_MAP_TO_PIN_BASE) +
-		  GIC_SH_MAP_TO_PIN(intr), GIC_MAP_TO_PIN_MSK | pin);
+	gic_write32(GIC_REG(SHARED, GIC_SH_INTR_MAP_TO_PIN_BASE) +
+		    GIC_SH_MAP_TO_PIN(intr), GIC_MAP_TO_PIN_MSK | pin);
 }
 
 static inline void gic_map_to_vpe(unsigned int intr, unsigned int vpe)
@@ -115,9 +141,9 @@ cycle_t gic_read_count(void)
 	unsigned int hi, hi2, lo;
 
 	do {
-		hi = gic_read(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
-		lo = gic_read(GIC_REG(SHARED, GIC_SH_COUNTER_31_00));
-		hi2 = gic_read(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
+		hi = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
+		lo = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_31_00));
+		hi2 = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
 	} while (hi2 != hi);
 
 	return (((cycle_t) hi) << 32) + lo;
@@ -136,9 +162,9 @@ unsigned int gic_get_count_width(void)
 
 void gic_write_compare(cycle_t cnt)
 {
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
 				(int)(cnt >> 32));
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
 				(int)(cnt & 0xffffffff));
 }
 
@@ -148,10 +174,10 @@ void gic_write_cpu_compare(cycle_t cnt, int cpu)
 
 	local_irq_save(flags);
 
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
-	gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
+	gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
 				(int)(cnt >> 32));
-	gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
+	gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
 				(int)(cnt & 0xffffffff));
 
 	local_irq_restore(flags);
@@ -161,8 +187,8 @@ cycle_t gic_read_compare(void)
 {
 	unsigned int hi, lo;
 
-	hi = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI));
-	lo = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO));
+	hi = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI));
+	lo = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO));
 
 	return (((cycle_t) hi) << 32) + lo;
 }
@@ -197,7 +223,7 @@ static bool gic_local_irq_is_routable(int intr)
 	if (cpu_has_veic)
 		return true;
 
-	vpe_ctl = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_CTL));
+	vpe_ctl = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_CTL));
 	switch (intr) {
 	case GIC_LOCAL_INT_TIMER:
 		return vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK;
@@ -273,7 +299,7 @@ int gic_get_c0_fdc_int(void)
 
 static void gic_handle_shared_int(bool chained)
 {
-	unsigned int i, intr, virq;
+	unsigned int i, intr, virq, gic_reg_step = mips_cm_is64 ? 8 : 4;
 	unsigned long *pcpu_mask;
 	unsigned long pending_reg, intrmask_reg;
 	DECLARE_BITMAP(pending, GIC_MAX_INTRS);
@@ -288,8 +314,8 @@ static void gic_handle_shared_int(bool chained)
 	for (i = 0; i < BITS_TO_LONGS(gic_shared_intrs); i++) {
 		pending[i] = gic_read(pending_reg);
 		intrmask[i] = gic_read(intrmask_reg);
-		pending_reg += 0x4;
-		intrmask_reg += 0x4;
+		pending_reg += gic_reg_step;
+		intrmask_reg += gic_reg_step;
 	}
 
 	bitmap_and(pending, pending, intrmask, gic_shared_intrs);
@@ -439,8 +465,8 @@ static void gic_handle_local_int(bool chained)
 	unsigned long pending, masked;
 	unsigned int intr, virq;
 
-	pending = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_PEND));
-	masked = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_MASK));
+	pending = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_PEND));
+	masked = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_MASK));
 
 	bitmap_and(&pending, &pending, &masked, GIC_NUM_LOCAL_INTRS);
 
@@ -463,14 +489,14 @@ static void gic_mask_local_irq(struct irq_data *d)
 {
 	int intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
 
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_RMASK), 1 << intr);
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_RMASK), 1 << intr);
 }
 
 static void gic_unmask_local_irq(struct irq_data *d)
 {
 	int intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
 
-	gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), 1 << intr);
+	gic_write32(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), 1 << intr);
 }
 
 static struct irq_chip gic_local_irq_controller = {
@@ -488,7 +514,7 @@ static void gic_mask_local_irq_all_vpes(struct irq_data *d)
 	spin_lock_irqsave(&gic_lock, flags);
 	for (i = 0; i < gic_vpes; i++) {
 		gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
-		gic_write(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << intr);
+		gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << intr);
 	}
 	spin_unlock_irqrestore(&gic_lock, flags);
 }
@@ -502,7 +528,7 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
 	spin_lock_irqsave(&gic_lock, flags);
 	for (i = 0; i < gic_vpes; i++) {
 		gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
-		gic_write(GIC_REG(VPE_OTHER, GIC_VPE_SMASK), 1 << intr);
+		gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SMASK), 1 << intr);
 	}
 	spin_unlock_irqrestore(&gic_lock, flags);
 }
@@ -622,7 +648,7 @@ static void __init gic_basic_init(void)
 		for (j = 0; j < GIC_NUM_LOCAL_INTRS; j++) {
 			if (!gic_local_irq_is_routable(j))
 				continue;
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << j);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_RMASK), 1 << j);
 		}
 	}
 }
@@ -667,27 +693,32 @@ static int gic_local_irq_domain_map(struct irq_domain *d, unsigned int virq,
 
 		switch (intr) {
 		case GIC_LOCAL_INT_WD:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_WD_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_WD_MAP), val);
 			break;
 		case GIC_LOCAL_INT_COMPARE:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_TIMER:
 			/* CONFIG_MIPS_CMP workaround (see __gic_init) */
 			val = GIC_MAP_TO_PIN_MSK | timer_cpu_pin;
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_PERFCTR:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_SWINT0:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_SWINT0_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SWINT0_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_SWINT1:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_SWINT1_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_SWINT1_MAP),
+				    val);
 			break;
 		case GIC_LOCAL_INT_FDC:
-			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_FDC_MAP), val);
+			gic_write32(GIC_REG(VPE_OTHER, GIC_VPE_FDC_MAP), val);
 			break;
 		default:
 			pr_err("Invalid local IRQ %d\n", intr);
@@ -792,7 +823,7 @@ static void __init __gic_init(unsigned long gic_base_addr,
 		 */
 		if (IS_ENABLED(CONFIG_MIPS_CMP) &&
 		    gic_local_irq_is_routable(GIC_LOCAL_INT_TIMER)) {
-			timer_cpu_pin = gic_read(GIC_REG(VPE_LOCAL,
+			timer_cpu_pin = gic_read32(GIC_REG(VPE_LOCAL,
 							 GIC_VPE_TIMER_MAP)) &
 					GIC_MAP_MSK;
 			irq_set_chained_handler(MIPS_CPU_IRQ_BASE +
diff --git a/include/linux/irqchip/mips-gic.h b/include/linux/irqchip/mips-gic.h
index 9b1ad3734911..10e4a9073019 100644
--- a/include/linux/irqchip/mips-gic.h
+++ b/include/linux/irqchip/mips-gic.h
@@ -45,8 +45,14 @@
 #define GIC_SH_REVISIONID_OFS		0x0020
 
 /* Convert an interrupt number to a byte offset/bit for multi-word registers */
-#define GIC_INTR_OFS(intr)		(((intr) / 32) * 4)
-#define GIC_INTR_BIT(intr)		((intr) % 32)
+#define GIC_INTR_OFS(intr) ({				\
+	unsigned bits = mips_cm_is64 ? 64 : 32;		\
+	unsigned reg_idx = (intr) / bits;		\
+	unsigned reg_width = bits / 8;			\
+							\
+	reg_idx * reg_width;				\
+})
+#define GIC_INTR_BIT(intr)		((intr) % (mips_cm_is64 ? 64 : 32))
 
 /* Polarity : Reset Value is always 0 */
 #define GIC_SH_SET_POLARITY_OFS		0x0100
-- 
2.4.5

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

* Re: [PATCH v2 14/19] drivers: irqchip: irq-mips-gic: Extend GIC accessors for 64-bit CMs
  2015-07-14  9:26     ` Markos Chandras
  (?)
@ 2015-07-14 11:57     ` Jonas Gorski
  2015-07-14 12:21       ` Markos Chandras
  -1 siblings, 1 reply; 65+ messages in thread
From: Jonas Gorski @ 2015-07-14 11:57 UTC (permalink / raw)
  To: Markos Chandras
  Cc: MIPS Mailing List, Thomas Gleixner, Jason Cooper,
	Andrew Bresticker, Paul Burton

Hi,

On Tue, Jul 14, 2015 at 11:26 AM, Markos Chandras
<markos.chandras@imgtec.com> wrote:
> Previously, the GIC accessors were only accessing u32 registers but
> newer CMs may actually be 64-bit on MIPS64 cores. As a result of which,
> extended these accessors to support 64-bit reads and writes.

Have you tested this with a 32-bit build? IIRC the *q accessors are
only available on 64-bit builds.


Jonas

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

* Re: [PATCH v2 14/19] drivers: irqchip: irq-mips-gic: Extend GIC accessors for 64-bit CMs
  2015-07-14 11:57     ` Jonas Gorski
@ 2015-07-14 12:21       ` Markos Chandras
  0 siblings, 0 replies; 65+ messages in thread
From: Markos Chandras @ 2015-07-14 12:21 UTC (permalink / raw)
  To: Jonas Gorski
  Cc: MIPS Mailing List, Thomas Gleixner, Jason Cooper,
	Andrew Bresticker, Paul Burton

On 07/14/2015 12:57 PM, Jonas Gorski wrote:
> Hi,
> 
> On Tue, Jul 14, 2015 at 11:26 AM, Markos Chandras
> <markos.chandras@imgtec.com> wrote:
>> Previously, the GIC accessors were only accessing u32 registers but
>> newer CMs may actually be 64-bit on MIPS64 cores. As a result of which,
>> extended these accessors to support 64-bit reads and writes.
> 
> Have you tested this with a 32-bit build? IIRC the *q accessors are
> only available on 64-bit builds.
> 
> 
> Jonas
> 
Yes but mips_cm_is64 is 0 for 32-bit kernels (see
https://patchwork.linux-mips.org/patch/10707/) so it does not matter.
but mips implements *q for 32-bit in arch/mips/include/asm/io.h anyway

-- 
markos

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

end of thread, other threads:[~2015-07-14 12:21 UTC | newest]

Thread overview: 65+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-09  9:40 [PATCH 00/19] Initial I6400 and CM3 support Markos Chandras
2015-07-09  9:40 ` Markos Chandras
2015-07-09  9:40 ` [PATCH 01/19] MIPS: Add MIPS I6400 PRid and cputype identifiers Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09  9:40 ` [PATCH 02/19] MIPS: Add cases for CPU_I6400 Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09 10:03   ` Ralf Baechle
2015-07-09 10:14     ` Markos Chandras
2015-07-09 10:14       ` Markos Chandras
2015-07-09 11:43       ` Ralf Baechle
2015-07-09  9:40 ` [PATCH 03/19] MIPS: Add MIPS I6400 probe support Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09  9:40 ` [PATCH 04/19] MIPS: Kconfig: Disable MIPS MT and SMP implementations for R6 Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09  9:40 ` [PATCH 05/19] MIPS: asm: mips-cm: Implement mips_cm_revision Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09 11:09   ` Sergei Shtylyov
2015-07-09 16:05     ` Markos Chandras
2015-07-09 16:05       ` Markos Chandras
2015-07-09 11:29   ` James Hogan
2015-07-09 11:29     ` James Hogan
2015-07-09 16:05     ` Markos Chandras
2015-07-09 16:05       ` Markos Chandras
2015-07-10  9:12   ` [PATCH v2 " Markos Chandras
2015-07-10  9:12     ` Markos Chandras
2015-07-09  9:40 ` [PATCH 06/19] MIPS: asm: add CM GCR_L2_CONFIG register accessors Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09  9:40 ` [PATCH 07/19] MIPS: mm: c-r4k: extend way_string array Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09  9:40 ` [PATCH 08/19] MIPS: support CM3 L2 cache Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09  9:40 ` [PATCH 09/19] MIPS: Add platform callback before initializing the " Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09  9:40 ` [PATCH 10/19] MIPS: asm: mips-cm: Extend CM accessors for 64-bit CPUs Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-14  8:14   ` [PATCH v2 " Markos Chandras
2015-07-14  8:14     ` Markos Chandras
2015-07-14  8:30     ` Paul Burton
2015-07-14  8:30       ` Paul Burton
2015-07-14  8:35       ` Paul Burton
2015-07-14  8:35         ` Paul Burton
2015-07-14  8:45         ` Markos Chandras
2015-07-14  8:45           ` Markos Chandras
2015-07-09  9:40 ` [PATCH 11/19] MIPS: kernel: mips-cm: The CMGCRBase register is 64-bit on MIPS64 Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09  9:40 ` [PATCH 12/19] MIPS: kernel: mips-cpc: Fix type for GCR CPC base reg for 64-bit Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09  9:40 ` [PATCH 13/19] MIPS: kernel: mips-cm: Add support for reporting CM cache errors Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09  9:40 ` [PATCH 14/19] drivers: irqchip: irq-mips-gic: Extend GIC accessors for 64-bit CMs Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-14  9:26   ` [PATCH v2 " Markos Chandras
2015-07-14  9:26     ` Markos Chandras
2015-07-14 11:57     ` Jonas Gorski
2015-07-14 12:21       ` Markos Chandras
2015-07-09  9:40 ` [PATCH 15/19] drivers: irqchip: irq-mips-gic: Add support for CM3 64-bit timer irqs Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09  9:40 ` [PATCH 16/19] MIPS: kernel: cpu-probe: Remove cp0 hazard barrier when enabling the FTLB Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09  9:40 ` [PATCH 17/19] MIPS: Add default case for the FTLB enable/disable code Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09  9:40 ` [PATCH 18/19] MIPS: kernel: cpu-probe: Fix VTLB/FTLB configuration for R6 Markos Chandras
2015-07-09  9:40   ` Markos Chandras
2015-07-09  9:40 ` [PATCH 19/19] MIPS: Set up FTLB probability for I6400 Markos Chandras
2015-07-09  9:40   ` Markos Chandras

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.