diff mbox series

Revert "riscv: Clean up IPI initialization code"

Message ID 1594184579-30271-1-git-send-email-bmeng.cn@gmail.com
State New
Headers show
Series Revert "riscv: Clean up IPI initialization code" | expand

Commit Message

Bin Meng July 8, 2020, 5:02 a.m. UTC
From: Bin Meng <bin.meng at windriver.com>

This reverts commit 40686c394e533fec765fe237936e353c84e73fff.

Commit 40686c394e53 ("riscv: Clean up IPI initialization code")
caused U-Boot failed to boot on SiFive HiFive Unleashed board.

The codes inside arch_cpu_init_dm() may call U-Boot timer APIs
before the call to riscv_init_ipi(). At that time the timer register
base (e.g.: the SiFive CLINT device in this case) is unknown yet.

It might be the name riscv_init_ipi() that misleads people to only
consider it is related to IPI, but in fact the timer capability is
provided by the same SiFive CLINT device that provides the IPI.
Timer capability is needed for both UP and SMP.

As the commit was a clean up attempt which did not bring in any
other benefits than to break the SiFive HiFive Unleashed board,
revert it.

Signed-off-by: Bin Meng <bin.meng at windriver.com>
---

 arch/riscv/cpu/cpu.c          |  6 ------
 arch/riscv/include/asm/smp.h  | 43 -------------------------------------
 arch/riscv/lib/andes_plic.c   | 34 +++++++++++++++++++-----------
 arch/riscv/lib/sbi_ipi.c      |  5 -----
 arch/riscv/lib/sifive_clint.c | 33 +++++++++++++++++++----------
 arch/riscv/lib/smp.c          | 49 ++++++++++++++++++++++++++++++++++++-------
 common/spl/spl_opensbi.c      |  5 -----
 7 files changed, 86 insertions(+), 89 deletions(-)
diff mbox series

Patch

diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c
index bbd6c15..d8b98ad 100644
--- a/arch/riscv/cpu/cpu.c
+++ b/arch/riscv/cpu/cpu.c
@@ -107,12 +107,6 @@  int arch_cpu_init_dm(void)
 #endif
 	}
 
-#ifdef CONFIG_SMP
-	ret = riscv_init_ipi();
-	if (ret)
-		return ret;
-#endif
-
 	return 0;
 }
 
diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h
index 1b42885..74de92e 100644
--- a/arch/riscv/include/asm/smp.h
+++ b/arch/riscv/include/asm/smp.h
@@ -51,47 +51,4 @@  void handle_ipi(ulong hart);
  */
 int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait);
 
-/**
- * riscv_init_ipi() - Initialize inter-process interrupt (IPI) driver
- *
- * Platform code must provide this function. This function is called once after
- * the cpu driver is initialized. No other riscv_*_ipi() calls will be made
- * before this function is called.
- *
- * @return 0 if OK, -ve on error
- */
-int riscv_init_ipi(void);
-
-/**
- * riscv_send_ipi() - Send inter-processor interrupt (IPI)
- *
- * Platform code must provide this function.
- *
- * @hart: Hart ID of receiving hart
- * @return 0 if OK, -ve on error
- */
-int riscv_send_ipi(int hart);
-
-/**
- * riscv_clear_ipi() - Clear inter-processor interrupt (IPI)
- *
- * Platform code must provide this function.
- *
- * @hart: Hart ID of hart to be cleared
- * @return 0 if OK, -ve on error
- */
-int riscv_clear_ipi(int hart);
-
-/**
- * riscv_get_ipi() - Get status of inter-processor interrupt (IPI)
- *
- * Platform code must provide this function.
- *
- * @hart: Hart ID of hart to be checked
- * @pending: Pointer to variable with result of the check,
- *           1 if IPI is pending, 0 otherwise
- * @return 0 if OK, -ve on error
- */
-int riscv_get_ipi(int hart, int *pending);
-
 #endif
diff --git a/arch/riscv/lib/andes_plic.c b/arch/riscv/lib/andes_plic.c
index 5cf29df..20529ab 100644
--- a/arch/riscv/lib/andes_plic.c
+++ b/arch/riscv/lib/andes_plic.c
@@ -30,6 +30,20 @@ 
 #define SEND_IPI_TO_HART(hart)  (0x80 >> (hart))
 
 DECLARE_GLOBAL_DATA_PTR;
+static int init_plic(void);
+
+#define PLIC_BASE_GET(void)						\
+	do {								\
+		long *ret;						\
+									\
+		if (!gd->arch.plic) {					\
+			ret = syscon_get_first_range(RISCV_SYSCON_PLIC); \
+			if (IS_ERR(ret))				\
+				return PTR_ERR(ret);			\
+			gd->arch.plic = ret;				\
+			init_plic();					\
+		}							\
+	} while (0)
 
 static int enable_ipi(int hart)
 {
@@ -79,21 +93,13 @@  static int init_plic(void)
 	return -ENODEV;
 }
 
-int riscv_init_ipi(void)
-{
-	long *ret = syscon_get_first_range(RISCV_SYSCON_PLIC);
-
-	if (IS_ERR(ret))
-		return PTR_ERR(ret);
-	gd->arch.plic = ret;
-
-	return init_plic();
-}
-
 int riscv_send_ipi(int hart)
 {
-	unsigned int ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart));
+	unsigned int ipi;
+
+	PLIC_BASE_GET();
 
+	ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart));
 	writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plic,
 				gd->arch.boot_hart));
 
@@ -104,6 +110,8 @@  int riscv_clear_ipi(int hart)
 {
 	u32 source_id;
 
+	PLIC_BASE_GET();
+
 	source_id = readl((void __iomem *)CLAIM_REG(gd->arch.plic, hart));
 	writel(source_id, (void __iomem *)CLAIM_REG(gd->arch.plic, hart));
 
@@ -112,6 +120,8 @@  int riscv_clear_ipi(int hart)
 
 int riscv_get_ipi(int hart, int *pending)
 {
+	PLIC_BASE_GET();
+
 	*pending = readl((void __iomem *)PENDING_REG(gd->arch.plic,
 						     gd->arch.boot_hart));
 	*pending = !!(*pending & SEND_IPI_TO_HART(hart));
diff --git a/arch/riscv/lib/sbi_ipi.c b/arch/riscv/lib/sbi_ipi.c
index d02e2b4..abafca9 100644
--- a/arch/riscv/lib/sbi_ipi.c
+++ b/arch/riscv/lib/sbi_ipi.c
@@ -8,11 +8,6 @@ 
 #include <asm/encoding.h>
 #include <asm/sbi.h>
 
-int riscv_init_ipi(void)
-{
-	return 0;
-}
-
 int riscv_send_ipi(int hart)
 {
 	ulong mask;
diff --git a/arch/riscv/lib/sifive_clint.c b/arch/riscv/lib/sifive_clint.c
index 78fc6c8..5e0d257 100644
--- a/arch/riscv/lib/sifive_clint.c
+++ b/arch/riscv/lib/sifive_clint.c
@@ -24,8 +24,22 @@ 
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define CLINT_BASE_GET(void)						\
+	do {								\
+		long *ret;						\
+									\
+		if (!gd->arch.clint) {					\
+			ret = syscon_get_first_range(RISCV_SYSCON_CLINT); \
+			if (IS_ERR(ret))				\
+				return PTR_ERR(ret);			\
+			gd->arch.clint = ret;				\
+		}							\
+	} while (0)
+
 int riscv_get_time(u64 *time)
 {
+	CLINT_BASE_GET();
+
 	*time = readq((void __iomem *)MTIME_REG(gd->arch.clint));
 
 	return 0;
@@ -33,24 +47,17 @@  int riscv_get_time(u64 *time)
 
 int riscv_set_timecmp(int hart, u64 cmp)
 {
-	writeq(cmp, (void __iomem *)MTIMECMP_REG(gd->arch.clint, hart));
-
-	return 0;
-}
-
-int riscv_init_ipi(void)
-{
-	long *ret = syscon_get_first_range(RISCV_SYSCON_CLINT);
+	CLINT_BASE_GET();
 
-	if (IS_ERR(ret))
-		return PTR_ERR(ret);
-	gd->arch.clint = ret;
+	writeq(cmp, (void __iomem *)MTIMECMP_REG(gd->arch.clint, hart));
 
 	return 0;
 }
 
 int riscv_send_ipi(int hart)
 {
+	CLINT_BASE_GET();
+
 	writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
 
 	return 0;
@@ -58,6 +65,8 @@  int riscv_send_ipi(int hart)
 
 int riscv_clear_ipi(int hart)
 {
+	CLINT_BASE_GET();
+
 	writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
 
 	return 0;
@@ -65,6 +74,8 @@  int riscv_clear_ipi(int hart)
 
 int riscv_get_ipi(int hart, int *pending)
 {
+	CLINT_BASE_GET();
+
 	*pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart));
 
 	return 0;
diff --git a/arch/riscv/lib/smp.c b/arch/riscv/lib/smp.c
index ac22136..17adb35 100644
--- a/arch/riscv/lib/smp.c
+++ b/arch/riscv/lib/smp.c
@@ -12,6 +12,38 @@ 
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/**
+ * riscv_send_ipi() - Send inter-processor interrupt (IPI)
+ *
+ * Platform code must provide this function.
+ *
+ * @hart: Hart ID of receiving hart
+ * @return 0 if OK, -ve on error
+ */
+extern int riscv_send_ipi(int hart);
+
+/**
+ * riscv_clear_ipi() - Clear inter-processor interrupt (IPI)
+ *
+ * Platform code must provide this function.
+ *
+ * @hart: Hart ID of hart to be cleared
+ * @return 0 if OK, -ve on error
+ */
+extern int riscv_clear_ipi(int hart);
+
+/**
+ * riscv_get_ipi() - Get status of inter-processor interrupt (IPI)
+ *
+ * Platform code must provide this function.
+ *
+ * @hart: Hart ID of hart to be checked
+ * @pending: Pointer to variable with result of the check,
+ *           1 if IPI is pending, 0 otherwise
+ * @return 0 if OK, -ve on error
+ */
+extern int riscv_get_ipi(int hart, int *pending);
+
 static int send_ipi_many(struct ipi_data *ipi, int wait)
 {
 	ofnode node, cpus;
@@ -92,7 +124,7 @@  void handle_ipi(ulong hart)
 	 */
 	ret = riscv_clear_ipi(hart);
 	if (ret) {
-		pr_err("Cannot clear IPI of hart %ld (error %d)\n", hart, ret);
+		pr_err("Cannot clear IPI of hart %ld\n", hart);
 		return;
 	}
 
@@ -101,11 +133,14 @@  void handle_ipi(ulong hart)
 
 int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait)
 {
-	struct ipi_data ipi = {
-		.addr = addr,
-		.arg0 = arg0,
-		.arg1 = arg1,
-	};
+	int ret = 0;
+	struct ipi_data ipi;
+
+	ipi.addr = addr;
+	ipi.arg0 = arg0;
+	ipi.arg1 = arg1;
+
+	ret = send_ipi_many(&ipi, wait);
 
-	return send_ipi_many(&ipi, wait);
+	return ret;
 }
diff --git a/common/spl/spl_opensbi.c b/common/spl/spl_opensbi.c
index 3440bc0..14f335f 100644
--- a/common/spl/spl_opensbi.c
+++ b/common/spl/spl_opensbi.c
@@ -79,11 +79,6 @@  void spl_invoke_opensbi(struct spl_image_info *spl_image)
 	invalidate_icache_all();
 
 #ifdef CONFIG_SPL_SMP
-	/* Initialize the IPI before we use it */
-	ret = riscv_init_ipi();
-	if (ret)
-		hang();
-
 	/*
 	 * Start OpenSBI on all secondary harts and wait for acknowledgment.
 	 *