]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
riscv: Clean up IPI initialization code
authorSean Anderson <seanga2@gmail.com>
Wed, 24 Jun 2020 10:41:18 +0000 (06:41 -0400)
committerAndes <uboot@andestech.com>
Wed, 1 Jul 2020 07:01:22 +0000 (15:01 +0800)
The previous IPI code initialized the device whenever the first call was
made to a riscv_*_ipi function. This made it difficult to determine when
the IPI device was initialized. This patch introduces a new function
riscv_init_ipi. It is called once during arch_cpu_init_dm. In SPL, it is
called in spl_invoke_opensbi. Before this point, no riscv_*_ipi functions
should be called.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
Reviewed-by: Rick Chen <rick@andestech.com>
arch/riscv/cpu/cpu.c
arch/riscv/include/asm/smp.h
arch/riscv/lib/andes_plic.c
arch/riscv/lib/sbi_ipi.c
arch/riscv/lib/sifive_clint.c
arch/riscv/lib/smp.c
common/spl/spl_opensbi.c

index 5804aa8e737727dc1cada61a6b23f23106518058..d75a3f045ae1b052546796560d9781ccd84d44dd 100644 (file)
@@ -98,6 +98,12 @@ int arch_cpu_init_dm(void)
                        csr_write(CSR_SATP, 0);
        }
 
+#ifdef CONFIG_SMP
+       ret = riscv_init_ipi();
+       if (ret)
+               return ret;
+#endif
+
        return 0;
 }
 
index 74de92ed130ebb4bfae1050581c70183a563746b..1b428856b26dbd288988d0cb3f5d4e8f0663337c 100644 (file)
@@ -51,4 +51,47 @@ 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
index 20529ab3eb58899ffca8790558494e34e9a370b3..5cf29df670cc8a8486fc39fc35f3b128bb00245a 100644 (file)
 #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)
 {
@@ -93,13 +79,21 @@ static int init_plic(void)
        return -ENODEV;
 }
 
-int riscv_send_ipi(int hart)
+int riscv_init_ipi(void)
 {
-       unsigned int ipi;
+       long *ret = syscon_get_first_range(RISCV_SYSCON_PLIC);
+
+       if (IS_ERR(ret))
+               return PTR_ERR(ret);
+       gd->arch.plic = ret;
+
+       return init_plic();
+}
 
-       PLIC_BASE_GET();
+int riscv_send_ipi(int hart)
+{
+       unsigned int ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart));
 
-       ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart));
        writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plic,
                                gd->arch.boot_hart));
 
@@ -110,8 +104,6 @@ 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));
 
@@ -120,8 +112,6 @@ 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));
index abafca9e5c1366d18608272f328d1cc79560dd02..d02e2b4c4882385156b2a7484902a73455f52239 100644 (file)
@@ -8,6 +8,11 @@
 #include <asm/encoding.h>
 #include <asm/sbi.h>
 
+int riscv_init_ipi(void)
+{
+       return 0;
+}
+
 int riscv_send_ipi(int hart)
 {
        ulong mask;
index 5e0d25720bdabd6d4aaf0608afe230cb2395c0f9..78fc6c868dd0dcfba1db009136b5481622ad9c40 100644 (file)
 
 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;
@@ -47,17 +33,24 @@ int riscv_get_time(u64 *time)
 
 int riscv_set_timecmp(int hart, u64 cmp)
 {
-       CLINT_BASE_GET();
-
        writeq(cmp, (void __iomem *)MTIMECMP_REG(gd->arch.clint, hart));
 
        return 0;
 }
 
-int riscv_send_ipi(int hart)
+int riscv_init_ipi(void)
 {
-       CLINT_BASE_GET();
+       long *ret = syscon_get_first_range(RISCV_SYSCON_CLINT);
+
+       if (IS_ERR(ret))
+               return PTR_ERR(ret);
+       gd->arch.clint = ret;
+
+       return 0;
+}
 
+int riscv_send_ipi(int hart)
+{
        writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
 
        return 0;
@@ -65,8 +58,6 @@ 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;
@@ -74,8 +65,6 @@ 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;
index 17adb35730d83c08d67f477c534379cd561fe5c7..ac22136314f647b0a7a10a27199ce39d385ea9f9 100644 (file)
 
 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;
@@ -124,7 +92,7 @@ void handle_ipi(ulong hart)
         */
        ret = riscv_clear_ipi(hart);
        if (ret) {
-               pr_err("Cannot clear IPI of hart %ld\n", hart);
+               pr_err("Cannot clear IPI of hart %ld (error %d)\n", hart, ret);
                return;
        }
 
@@ -133,14 +101,11 @@ void handle_ipi(ulong hart)
 
 int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait)
 {
-       int ret = 0;
-       struct ipi_data ipi;
-
-       ipi.addr = addr;
-       ipi.arg0 = arg0;
-       ipi.arg1 = arg1;
-
-       ret = send_ipi_many(&ipi, wait);
+       struct ipi_data ipi = {
+               .addr = addr,
+               .arg0 = arg0,
+               .arg1 = arg1,
+       };
 
-       return ret;
+       return send_ipi_many(&ipi, wait);
 }
index e88136e6f39ed8528bb5a2460624f178f06092b9..defddac8f29880275725f46aadf145309bf92257 100644 (file)
@@ -79,6 +79,11 @@ 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.
         *