riscv: Clean up IPI initialization code
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>
This commit is contained in:
		
							parent
							
								
									9472630337
								
							
						
					
					
						commit
						40686c394e
					
				|  | @ -98,6 +98,12 @@ int arch_cpu_init_dm(void) | ||||||
| 			csr_write(CSR_SATP, 0); | 			csr_write(CSR_SATP, 0); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_SMP | ||||||
|  | 	ret = riscv_init_ipi(); | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -51,4 +51,47 @@ void handle_ipi(ulong hart); | ||||||
|  */ |  */ | ||||||
| int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait); | 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 | #endif | ||||||
|  |  | ||||||
|  | @ -30,20 +30,6 @@ | ||||||
| #define SEND_IPI_TO_HART(hart)  (0x80 >> (hart)) | #define SEND_IPI_TO_HART(hart)  (0x80 >> (hart)) | ||||||
| 
 | 
 | ||||||
| DECLARE_GLOBAL_DATA_PTR; | 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) | static int enable_ipi(int hart) | ||||||
| { | { | ||||||
|  | @ -93,13 +79,21 @@ static int init_plic(void) | ||||||
| 	return -ENODEV; | 	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) | int riscv_send_ipi(int hart) | ||||||
| { | { | ||||||
| 	unsigned int ipi; | 	unsigned int ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart)); | ||||||
| 
 | 
 | ||||||
| 	PLIC_BASE_GET(); |  | ||||||
| 
 |  | ||||||
| 	ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart)); |  | ||||||
| 	writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plic, | 	writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plic, | ||||||
| 				gd->arch.boot_hart)); | 				gd->arch.boot_hart)); | ||||||
| 
 | 
 | ||||||
|  | @ -110,8 +104,6 @@ int riscv_clear_ipi(int hart) | ||||||
| { | { | ||||||
| 	u32 source_id; | 	u32 source_id; | ||||||
| 
 | 
 | ||||||
| 	PLIC_BASE_GET(); |  | ||||||
| 
 |  | ||||||
| 	source_id = readl((void __iomem *)CLAIM_REG(gd->arch.plic, hart)); | 	source_id = readl((void __iomem *)CLAIM_REG(gd->arch.plic, hart)); | ||||||
| 	writel(source_id, (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) | int riscv_get_ipi(int hart, int *pending) | ||||||
| { | { | ||||||
| 	PLIC_BASE_GET(); |  | ||||||
| 
 |  | ||||||
| 	*pending = readl((void __iomem *)PENDING_REG(gd->arch.plic, | 	*pending = readl((void __iomem *)PENDING_REG(gd->arch.plic, | ||||||
| 						     gd->arch.boot_hart)); | 						     gd->arch.boot_hart)); | ||||||
| 	*pending = !!(*pending & SEND_IPI_TO_HART(hart)); | 	*pending = !!(*pending & SEND_IPI_TO_HART(hart)); | ||||||
|  |  | ||||||
|  | @ -8,6 +8,11 @@ | ||||||
| #include <asm/encoding.h> | #include <asm/encoding.h> | ||||||
| #include <asm/sbi.h> | #include <asm/sbi.h> | ||||||
| 
 | 
 | ||||||
|  | int riscv_init_ipi(void) | ||||||
|  | { | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int riscv_send_ipi(int hart) | int riscv_send_ipi(int hart) | ||||||
| { | { | ||||||
| 	ulong mask; | 	ulong mask; | ||||||
|  |  | ||||||
|  | @ -24,22 +24,8 @@ | ||||||
| 
 | 
 | ||||||
| DECLARE_GLOBAL_DATA_PTR; | 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) | int riscv_get_time(u64 *time) | ||||||
| { | { | ||||||
| 	CLINT_BASE_GET(); |  | ||||||
| 
 |  | ||||||
| 	*time = readq((void __iomem *)MTIME_REG(gd->arch.clint)); | 	*time = readq((void __iomem *)MTIME_REG(gd->arch.clint)); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -47,17 +33,24 @@ int riscv_get_time(u64 *time) | ||||||
| 
 | 
 | ||||||
| int riscv_set_timecmp(int hart, u64 cmp) | int riscv_set_timecmp(int hart, u64 cmp) | ||||||
| { | { | ||||||
| 	CLINT_BASE_GET(); |  | ||||||
| 
 |  | ||||||
| 	writeq(cmp, (void __iomem *)MTIMECMP_REG(gd->arch.clint, hart)); | 	writeq(cmp, (void __iomem *)MTIMECMP_REG(gd->arch.clint, hart)); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int riscv_init_ipi(void) | ||||||
|  | { | ||||||
|  | 	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) | int riscv_send_ipi(int hart) | ||||||
| { | { | ||||||
| 	CLINT_BASE_GET(); |  | ||||||
| 
 |  | ||||||
| 	writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart)); | 	writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart)); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -65,8 +58,6 @@ int riscv_send_ipi(int hart) | ||||||
| 
 | 
 | ||||||
| int riscv_clear_ipi(int hart) | int riscv_clear_ipi(int hart) | ||||||
| { | { | ||||||
| 	CLINT_BASE_GET(); |  | ||||||
| 
 |  | ||||||
| 	writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart)); | 	writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart)); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -74,8 +65,6 @@ int riscv_clear_ipi(int hart) | ||||||
| 
 | 
 | ||||||
| int riscv_get_ipi(int hart, int *pending) | int riscv_get_ipi(int hart, int *pending) | ||||||
| { | { | ||||||
| 	CLINT_BASE_GET(); |  | ||||||
| 
 |  | ||||||
| 	*pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart)); | 	*pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart)); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  |  | ||||||
|  | @ -12,38 +12,6 @@ | ||||||
| 
 | 
 | ||||||
| DECLARE_GLOBAL_DATA_PTR; | 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) | static int send_ipi_many(struct ipi_data *ipi, int wait) | ||||||
| { | { | ||||||
| 	ofnode node, cpus; | 	ofnode node, cpus; | ||||||
|  | @ -124,7 +92,7 @@ void handle_ipi(ulong hart) | ||||||
| 	 */ | 	 */ | ||||||
| 	ret = riscv_clear_ipi(hart); | 	ret = riscv_clear_ipi(hart); | ||||||
| 	if (ret) { | 	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; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -133,14 +101,11 @@ void handle_ipi(ulong hart) | ||||||
| 
 | 
 | ||||||
| int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait) | int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait) | ||||||
| { | { | ||||||
| 	int ret = 0; | 	struct ipi_data ipi = { | ||||||
| 	struct ipi_data ipi; | 		.addr = addr, | ||||||
|  | 		.arg0 = arg0, | ||||||
|  | 		.arg1 = arg1, | ||||||
|  | 	}; | ||||||
| 
 | 
 | ||||||
| 	ipi.addr = addr; | 	return send_ipi_many(&ipi, wait); | ||||||
| 	ipi.arg0 = arg0; |  | ||||||
| 	ipi.arg1 = arg1; |  | ||||||
| 
 |  | ||||||
| 	ret = send_ipi_many(&ipi, wait); |  | ||||||
| 
 |  | ||||||
| 	return ret; |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -79,6 +79,11 @@ void spl_invoke_opensbi(struct spl_image_info *spl_image) | ||||||
| 	invalidate_icache_all(); | 	invalidate_icache_all(); | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_SPL_SMP | #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. | 	 * Start OpenSBI on all secondary harts and wait for acknowledgment. | ||||||
| 	 * | 	 * | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue