Add Andes AE350 fdt driver support
v3 cover Add Andes AE350 fdt driver support
We move the devices used by AE350 to fdt driver framework, reuse existing driver and add timer, ipi and reset drivers. The OpenSBI domain support is also enabled. As of now, we can use Kconfig to manage these configurations that can support variants of Andes platform and SoC like Kendryte K510.
Changes v2 -> v3
- Add PATCH1 and PATCH2 to fix typos
- Add PATCH3 which factors out function for adding mtimer and ipi device regions to root domain
- Remove unused variable "num_src" and "riscv,ndev" property of ipi device node
Yu Chien Peter Lin (13):
include: sbi: Fix typo in comment
lib: sbi: Fix typo in comment
lib: sbi: Add sbi_domain_root_add_memrange() API
platform: andes/ae350: Remove enabling cache from an350_final_init
platform: andes/ae350: Use kconfig to set platform version and default
name
platform: andes/ae350: Use fdt serial driver
lib: utils/timer: Add Andes fdt timer support
lib: utils/reset: Add Andes fdt reset driver support
platform: andes/ae350: Use fdt irqchip driver
platform: andes/ae350: Add fw_platform_init for platform
initialization
lib: utils/ipi: Add Andes fdt ipi driver support
platform: andes/ae350: Add AE350 domain support
docs: andes-ae350.md: Update ae350 documentation for fdt driver
support
docs/platform/andes-ae350.md | 184 +++++++++++++++++++++++- include/sbi/sbi_domain.h | 16 ++- include/sbi/sbi_scratch.h | 2 +- include/sbi_utils/fdt/fdt_helper.h | 6 + include/sbi_utils/ipi/andes_plicsw.h | 49 +++++++ include/sbi_utils/timer/aclint_mtimer.h | 2 + include/sbi_utils/timer/andes_plmt.h | 33 +++++ lib/sbi/sbi_domain.c | 27 ++++ lib/sbi/sbi_expected_trap.S | 2 +- lib/utils/fdt/fdt_helper.c | 109 ++++++++++++++ lib/utils/ipi/Kconfig | 9 ++ lib/utils/ipi/andes_plicsw.c | 85 +++++++++++ lib/utils/ipi/fdt_ipi_plicsw.c | 87 +++++++++++ lib/utils/ipi/objects.mk | 4 + lib/utils/reset/Kconfig | 4 + lib/utils/reset/fdt_reset_atcwdt200.c | 122 ++++++++++++++++ lib/utils/reset/objects.mk | 3 + lib/utils/timer/Kconfig | 9 ++ lib/utils/timer/aclint_mtimer.c | 50 ++----- lib/utils/timer/andes_plmt.c | 54 +++++++ lib/utils/timer/fdt_timer_plmt.c | 79 ++++++++++ lib/utils/timer/objects.mk | 4 + platform/andes/ae350/Kconfig | 30 +++- platform/andes/ae350/objects.mk | 2 +- platform/andes/ae350/platform.c | 165 +++++++++------------ platform/andes/ae350/platform.h | 17 --- platform/andes/ae350/plicsw.c | 139 ------------------ platform/andes/ae350/plicsw.h | 44 ------ platform/andes/ae350/plmt.c | 107 -------------- platform/andes/ae350/plmt.h | 17 --- 30 files changed, 995 insertions(+), 466 deletions(-) create mode 100644 include/sbi_utils/ipi/andes_plicsw.h create mode 100644 include/sbi_utils/timer/andes_plmt.h create mode 100644 lib/utils/ipi/andes_plicsw.c create mode 100644 lib/utils/ipi/fdt_ipi_plicsw.c create mode 100644 lib/utils/reset/fdt_reset_atcwdt200.c create mode 100644 lib/utils/timer/andes_plmt.c create mode 100644 lib/utils/timer/fdt_timer_plmt.c delete mode 100644 platform/andes/ae350/plicsw.c delete mode 100644 platform/andes/ae350/plicsw.h delete mode 100644 platform/andes/ae350/plmt.c delete mode 100644 platform/andes/ae350/plmt.h
Signature · 1 line
2.34.1
PATCH v3 1/13 include: sbi: Fix typo in comment
%s/Priviledge/Privilege
---
Changes v2 -> v3
- New patch
--- include/sbi/sbi_scratch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/sbi/sbi_scratch.h +1 -1
@@ -57,7 +57,7 @@ struct sbi_scratch {unsigned long next_arg1;/** Address of next booting stage for this HART */ unsigned long next_addr; -/** Priviledge mode of next booting stage for this HART */ +/** Privilege mode of next booting stage for this HART */ unsigned long next_mode;/** Warm boot entry point address for this HART */ unsigned long warmboot_addr;
Signature · 1 line
2.34.1
PATCH v3 1/13 include: sbi: Fix typo in comment
Quoted 4 lines · Yu Chien Peter Lin
%s/Priviledge/Privilege
Signed-off-by Yu Chien Peter Lin <[email protected]>
Looks good to me.
Regards,
Anup
Quoted 28 lines
---
Changes v2 -> v3
- New patch--- include/sbi/sbi_scratch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)include/sbi/sbi_scratch.h +1
-2@@ -57,7 +57,7 @@ struct sbi_scratch {unsigned long next_arg1;/** Address of next booting stage for this HART */ unsigned long next_addr; -/** Priviledge mode of next booting stage for this HART */ +/** Privilege mode of next booting stage for this HART */ unsigned long next_mode;/** Warm boot entry point address for this HART */ unsigned long warmboot_addr; --2.34.1
--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
PATCH v3 2/13 lib: sbi: Fix typo in comment
In reply to Yu Chien Peter Lin%s/is is/is
---
Changes v2 -> v3
- New patch
--- lib/sbi/sbi_expected_trap.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
lib/sbi/sbi_expected_trap.S +1 -1
@@ -11,7 +11,7 @@ #include <sbi/sbi_trap.h> /* - * We assume that faulting instruction is is 4-byte long and blindly + * We assume that faulting instruction is 4-byte long and blindly * increment SEPC by 4. * * The trap info will be saved as follows:
Signature · 1 line
2.34.1
PATCH v3 2/13 lib: sbi: Fix typo in comment
Quoted 4 lines · Yu Chien Peter Lin
%s/is is/is
Signed-off-by Yu Chien Peter Lin <[email protected]>
Looks good to me.
Regards,
Anup
Quoted 28 lines
---
Changes v2 -> v3
- New patch--- lib/sbi/sbi_expected_trap.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)lib/sbi/sbi_expected_trap.S +1
-2@@ -11,7 +11,7 @@ #include <sbi/sbi_trap.h> /* - * We assume that faulting instruction is is 4-byte long and blindly + * We assume that faulting instruction is 4-byte long and blindly * increment SEPC by 4. * * The trap info will be saved as follows: --2.34.1
--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
PATCH v3 3/13 lib: sbi: Add sbi_domain_root_add_memrange() API
In reply to Yu Chien Peter LinThis patch generalizes the logic to add a memory range with desired alignment and flags of consecutive regions to the root domain.
---
Changes v2 -> v3
- New patch
--- include/sbi/sbi_domain.h | 16 +++++++- include/sbi_utils/timer/aclint_mtimer.h | 2 + lib/sbi/sbi_domain.c | 27 +++++++++++++ lib/utils/timer/aclint_mtimer.c | 50 +++++++------------------ 4 files changed, 58 insertions(+), 37 deletions(-)
include/sbi/sbi_domain.h +15 -1
@@ -175,11 +175,25 @@ int sbi_domain_register(struct sbi_domain *dom,* @param reg pointer to the memory region to be added * * @return 0 on success -* @return SBI_EALREADY if memory region conflicts with existing +* @return SBI_EALREADY if memory region conflicts with the existing one * @return SBI_EINVAL otherwise */ int sbi_domain_root_add_memregion (const struct sbi_domain_memregion *reg); +/** +* Add a memory range with its flags to the root domain +* @param addr start physical address of memory range +* @param size physical size of memory range +* @param align alignment of memory region +* @param region_flags memory range flags +* +* @return 0 on success +* @return SBI_EALREADY if memory region conflicts with the existing one +* @return SBI_EINVAL otherwise +*/ +int sbi_domain_root_add_memrange (unsigned long addr,unsigned long size, +unsigned long align,unsigned long region_flags); +/** Finalize domain tables and startup non-root domains */ int sbi_domain_finalize (struct sbi_scratch *scratch,u32 cold_hartid);
include/sbi_utils/timer/aclint_mtimer.h +2 -0
@@ -22,6 +22,8 @@#define CLINT_MTIMER_OFFSET 0x4000 +#define MTIMER_REGION_ALIGN 0x1000 +struct aclint_mtimer_data {/* Public details */ unsigned long mtime_freq;
lib/sbi/sbi_domain.c +27 -0
@@ -522,6 +522,33 @@ int sbi_domain_root_add_memregion(const struct sbi_domain_memregion *reg)return 0 ; } +int sbi_domain_root_add_memrange (unsigned long addr,unsigned long size, +unsigned long align,unsigned long region_flags) +{ +int rc; +unsigned long pos, end, rsize; +struct sbi_domain_memregion reg; + + pos = addr; + end = addr + size; +while (pos < end) { + rsize = pos & (align -1 ); +if (rsize) + rsize =1UL <<sbi_ffs (pos); +else + rsize = ((end - pos) < align) ? + (end - pos) : align; + +sbi_domain_memregion_init (pos, rsize, region_flags, ®); + rc =sbi_domain_root_add_memregion (®); +if (rc) +return rc; + pos += rsize; + } + +return 0 ; +} +int sbi_domain_finalize (struct sbi_scratch *scratch,u32 cold_hartid) {int rc;
lib/utils/timer/aclint_mtimer.c +14 -36
71 lines not on this page · raw message
Signature · 1 line
2.34.1
PATCH v3 3/13 lib: sbi: Add sbi_domain_root_add_memrange() API
Quoted 20 lines · Yu Chien Peter Lin
This patch generalizes the logic to add a memory range with desired alignment and flags of consecutive regions to the root domain.
Signed-off-by Yu Chien Peter Lin <[email protected]>---
Changes v2 -> v3
- New patch--- include/sbi/sbi_domain.h | 16 +++++++- include/sbi_utils/timer/aclint_mtimer.h | 2 + lib/sbi/sbi_domain.c | 27 +++++++++++++ lib/utils/timer/aclint_mtimer.c | 50 +++++++------------------ 4 files changed, 58 insertions(+), 37 deletions(-)include/sbi/sbi_domain.h +0
-0
include/sbi/sbi_domain.h int sbi_domain_register(struct sbi_domain *dom, · line 178
Quoted 5 lines
include/sbi/sbi_domain.h +1
-1@@ -175,11 +175,25 @@ int sbi_domain_register(struct sbi_domain *dom,* @param reg pointer to the memory region to be added * * @return 0 on success -* @return SBI_EALREADY if memory region conflicts with existing +* @return SBI_EALREADY if memory region conflicts with the existing one
This could have been a separate patch or you could have mentioned about this typo fix in the commit description.
Quoted 153 lines
include/sbi/sbi_domain.h +14
-0* @return SBI_EINVAL otherwise */ int sbi_domain_root_add_memregion (const struct sbi_domain_memregion *reg); +/** +* Add a memory range with its flags to the root domain +* @param addr start physical address of memory range +* @param size physical size of memory range +* @param align alignment of memory region +* @param region_flags memory range flags +* +* @return 0 on success +* @return SBI_EALREADY if memory region conflicts with the existing one +* @return SBI_EINVAL otherwise +*/ +int sbi_domain_root_add_memrange (unsigned long addr,unsigned long size, +unsigned long align,unsigned long region_flags); +/** Finalize domain tables and startup non-root domains */ int sbi_domain_finalize (struct sbi_scratch *scratch,u32 cold_hartid);include/sbi_utils/timer/aclint_mtimer.h +2
-0@@ -22,6 +22,8 @@#define CLINT_MTIMER_OFFSET 0x4000 +#define MTIMER_REGION_ALIGN 0x1000 +struct aclint_mtimer_data {/* Public details */ unsigned long mtime_freq;lib/sbi/sbi_domain.c +27
-0@@ -522,6 +522,33 @@ int sbi_domain_root_add_memregion(const struct sbi_domain_memregion *reg)return 0 ; } +int sbi_domain_root_add_memrange (unsigned long addr,unsigned long size, +unsigned long align,unsigned long region_flags) +{ +int rc; +unsigned long pos, end, rsize; +struct sbi_domain_memregion reg; + + pos = addr; + end = addr + size; +while (pos < end) { + rsize = pos & (align -1 ); +if (rsize) + rsize =1UL <<sbi_ffs (pos); +else + rsize = ((end - pos) < align) ? + (end - pos) : align; + +sbi_domain_memregion_init (pos, rsize, region_flags, ®); + rc =sbi_domain_root_add_memregion (®); +if (rc) +return rc; + pos += rsize; + } + +return 0 ; +} +int sbi_domain_finalize (struct sbi_scratch *scratch,u32 cold_hartid) {int rc;lib/utils/timer/aclint_mtimer.c +14
-37@@ -142,34 +142,6 @@ int aclint_mtimer_warm_init(void)return 0 ; } -static int aclint_mtimer_add_regions (unsigned long addr,unsigned long size) -{ -#define MTIMER_ADD_REGION_ALIGN 0x1000 -int rc; -unsigned long pos, end, rsize; -struct sbi_domain_memregion reg; - - pos = addr; - end = addr + size; -while (pos < end) { - rsize = pos & (MTIMER_ADD_REGION_ALIGN -1 ); -if (rsize) - rsize =1UL <<sbi_ffs (pos); -else - rsize = ((end - pos) <MTIMER_ADD_REGION_ALIGN ) ? - (end - pos) :MTIMER_ADD_REGION_ALIGN ; - -sbi_domain_memregion_init (pos, rsize, -SBI_DOMAIN_MEMREGION_MMIO , ®); - rc =sbi_domain_root_add_memregion (®); -if (rc) -return rc; - pos += rsize; - } - -return 0 ; -} -int aclint_mtimer_cold_init (struct aclint_mtimer_data *mt,struct aclint_mtimer_data *reference) {@@ -208,23 +180,29 @@ int aclint_mtimer_cold_init(struct aclint_mtimer_data *mt,/* Add MTIMER regions to the root domain */ if (mt->mtime_addr == (mt->mtimecmp_addr + mt->mtimecmp_size)) { - rc =aclint_mtimer_add_regions (mt->mtimecmp_addr, - mt->mtime_size + mt->mtimecmp_size); + rc =sbi_domain_root_add_memrange (mt->mtimecmp_addr, + mt->mtime_size + mt->mtimecmp_size, +MTIMER_REGION_ALIGN , +SBI_DOMAIN_MEMREGION_MMIO );if (rc)return rc; }else if (mt->mtimecmp_addr == (mt->mtime_addr + mt->mtime_size)) { - rc =aclint_mtimer_add_regions (mt->mtime_addr, - mt->mtime_size + mt->mtimecmp_size); + rc =sbi_domain_root_add_memrange (mt->mtime_addr, + mt->mtime_size + mt->mtimecmp_size, +MTIMER_REGION_ALIGN , +SBI_DOMAIN_MEMREGION_MMIO );if (rc)return rc; }else { - rc =aclint_mtimer_add_regions (mt->mtime_addr, - mt->mtime_size); + rc =sbi_domain_root_add_memrange (mt->mtime_addr, + mt->mtime_size,MTIMER_REGION_ALIGN , +SBI_DOMAIN_MEMREGION_MMIO );if (rc)return rc; - rc =aclint_mtimer_add_regions (mt->mtimecmp_addr, - mt->mtimecmp_size); + rc =sbi_domain_root_add_memrange (mt->mtimecmp_addr, + mt->mtimecmp_size,MTIMER_REGION_ALIGN , +SBI_DOMAIN_MEMREGION_MMIO );if (rc)return rc; } --2.34.1
Quoted 4 lines
--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
Apart from a minor comment above, this looks good to me.
Regards,
Anup
PATCH v3 4/13 platform: andes/ae350: Remove enabling cache from an350_final_init
In reply to Yu Chien Peter LinThe boot-time cache operations have been handled by U-boot SPL, so we can drop duplicate code.
---
Changes v2 -> v3
- No change since v2
--- platform/andes/ae350/platform.c | 19 ------------------- 1 file changed, 19 deletions(-)
platform/andes/ae350/platform.c +0 -19
@@ -34,25 +34,6 @@ static int ae350_final_init(bool cold_boot) {void *fdt; -/* enable L1 cache */ -uintptr_t mcache_ctl_val =csr_read (CSR_MCACHECTL ); - -if (!(mcache_ctl_val &V5_MCACHE_CTL_IC_EN )) - mcache_ctl_val |=V5_MCACHE_CTL_IC_EN ; -if (!(mcache_ctl_val &V5_MCACHE_CTL_DC_EN )) - mcache_ctl_val |=V5_MCACHE_CTL_DC_EN ; -if (!(mcache_ctl_val &V5_MCACHE_CTL_CCTL_SUEN )) - mcache_ctl_val |=V5_MCACHE_CTL_CCTL_SUEN ; -csr_write (CSR_MCACHECTL , mcache_ctl_val); - -/* enable L2 cache */ -uint32_t *l2c_ctl_base = (void *)AE350_L2C_ADDR +V5_L2C_CTL_OFFSET ; -uint32_t l2c_ctl_val = *l2c_ctl_base; - -if (!(l2c_ctl_val &V5_L2C_CTL_ENABLE_MASK )) - l2c_ctl_val |=V5_L2C_CTL_ENABLE_MASK ; - *l2c_ctl_base = l2c_ctl_val; -if (!cold_boot)return 0 ;
Signature · 1 line
2.34.1
PATCH v3 5/13 platform: andes/ae350: Use kconfig to set platform version and default name
In reply to Yu Chien Peter LinThis patch makes andes platform name and version can be set in menuconfig interface.
---
Changes v2 -> v3
- No change since v2
--- platform/andes/ae350/Kconfig | 18 ++++++++++++++++++ platform/andes/ae350/platform.c | 6 ++++-- 2 files changed, 22 insertions(+), 2 deletions(-)
platform/andes/ae350/Kconfig +18 -0
@@ -6,3 +6,21 @@ config PLATFORM_ANDES_AE350 select IRQCHIP_PLIC select SERIAL_UART8250 default y + +if PLATFORM_ANDES_AE350 + +config PLATFORM_ANDES_AE350_NAME + string "Platform default name" + default "Andes AE350" + +config PLATFORM_ANDES_AE350_MAJOR_VER + int "Platform major version" + range 0 65535 + default 0 + +config PLATFORM_ANDES_AE350_MINOR_VER + int "Platform minor version" + range 0 65535 + default 1 + +endif
platform/andes/ae350/platform.c +4 -2
@@ -168,8 +168,10 @@ const struct sbi_platform_operations platform_ops = {const struct sbi_platform platform = { .opensbi_version =OPENSBI_VERSION , - .platform_version =SBI_PLATFORM_VERSION (0x0 ,0x01 ), - .name ="Andes AE350" , + .platform_version = +SBI_PLATFORM_VERSION (CONFIG_PLATFORM_ANDES_AE350_MAJOR_VER , +CONFIG_PLATFORM_ANDES_AE350_MINOR_VER ), + .name =CONFIG_PLATFORM_ANDES_AE350_NAME , .features =SBI_PLATFORM_DEFAULT_FEATURES , .hart_count =AE350_HART_COUNT , .hart_stack_size =SBI_PLATFORM_DEFAULT_HART_STACK_SIZE ,
Signature · 1 line
2.34.1
PATCH v3 6/13 platform: andes/ae350: Use fdt serial driver
In reply to Yu Chien Peter LinAndes UART is compatible with uart8250 driver. We can use fdt_serial_init() as platform console init hook.
dts example:
serial0: serial at f0300000 {
compatible = "andestech,uart16550", "ns16550a";
reg = <0x00000000 0xf0300000 0x00000000 0x00001000>;
interrupts = <9 4>;
interrupt-parent = <&plic0>;
clock-frequency = <19660800>;
current-speed = <38400>;
reg-shift = <2>;
reg-offset = <32>;
reg-io-width = <4>;
no-loopback-test = <1>;
};---
Changes v2 -> v3
- No change since v2
--- platform/andes/ae350/Kconfig | 3 ++- platform/andes/ae350/platform.c | 15 ++------------- platform/andes/ae350/platform.h | 8 -------- 3 files changed, 4 insertions(+), 22 deletions(-)
platform/andes/ae350/Kconfig +2 -1
@@ -4,7 +4,8 @@ config PLATFORM_ANDES_AE350 bool select FDT select IRQCHIP_PLIC - select SERIAL_UART8250 + select FDT_SERIAL + select FDT_SERIAL_UART8250 default y if PLATFORM_ANDES_AE350
platform/andes/ae350/platform.c +2 -13
@@ -18,7 +18,7 @@#include <sbi_utils/fdt/fdt_helper.h> #include <sbi_utils/fdt/fdt_fixup.h> #include <sbi_utils/irqchip/plic.h> -#include <sbi_utils/serial/uart8250.h> +#include <sbi_utils/serial/fdt_serial.h> #include "platform.h" #include "plicsw.h" #include "plmt.h"
@@ -43,17 +43,6 @@ static int ae350_final_init(bool cold_boot)return 0 ; } -/* Initialize the platform console. */ -static int ae350_console_init (void ) -{ -return uart8250_init (AE350_UART_ADDR , -AE350_UART_FREQUENCY , -AE350_UART_BAUDRATE , -AE350_UART_REG_SHIFT , -AE350_UART_REG_WIDTH , -AE350_UART_REG_OFFSET ); -} -/* Initialize the platform interrupt controller for current HART. */ static int ae350_irqchip_init (bool cold_boot) {
@@ -155,7 +144,7 @@ static int ae350_vendor_ext_provider(long extid, long funcid,const struct sbi_platform_operations platform_ops = { .final_init = ae350_final_init, - .console_init = ae350_console_init, + .console_init = fdt_serial_init, .irqchip_init = ae350_irqchip_init,
platform/andes/ae350/platform.h +0 -8
@@ -22,14 +22,6 @@#define AE350_L2C_ADDR 0xe0500000 -#define AE350_UART_ADDR_OFFSET 0x20 -#define AE350_UART_ADDR (0xf0300000 + AE350_UART_ADDR_OFFSET) -#define AE350_UART_FREQUENCY 19660800 -#define AE350_UART_BAUDRATE 38400 -#define AE350_UART_REG_SHIFT 2 -#define AE350_UART_REG_WIDTH 0 -#define AE350_UART_REG_OFFSET 0 -/*Memory and Miscellaneous Registers*/ #define CSR_MILMB 0x7c0#define CSR_MDLMB 0x7c1
Signature · 1 line
2.34.1
PATCH v3 7/13 lib: utils/timer: Add Andes fdt timer support
In reply to Yu Chien Peter LinSince we can get the PLMT base address and timer frequency from device tree, move plmt timer device to fdt timer framework.
dts example (Quad-core AX45MP):
cpus {
...
timebase-frequency = <0x3938700>;
...
}
soc {
...
plmt0 at e6000000 {
compatible = "andestech,plmt0";
reg = <0x00 0xe6000000 0x00 0x100000>;
interrupts-extended = <&cpu0_intc 0x07
&cpu1_intc 0x07
&cpu2_intc 0x07
&cpu3_intc 0x07>;
};
...
}---
Changes v2 -> v3
- Use sbi_domain_root_add_memrange() to add PLMT region to root domain
--- include/sbi_utils/fdt/fdt_helper.h | 3 + include/sbi_utils/timer/andes_plmt.h | 33 +++++++++ lib/utils/fdt/fdt_helper.c | 54 ++++++++++++++ lib/utils/timer/Kconfig | 9 +++ lib/utils/timer/andes_plmt.c | 54 ++++++++++++++ lib/utils/timer/fdt_timer_plmt.c | 79 ++++++++++++++++++++ lib/utils/timer/objects.mk | 4 + platform/andes/ae350/Kconfig | 2 + platform/andes/ae350/objects.mk | 2 +- platform/andes/ae350/platform.c | 19 +---- platform/andes/ae350/platform.h | 2 - platform/andes/ae350/plmt.c | 107 --------------------------- platform/andes/ae350/plmt.h | 17 ----- 13 files changed, 241 insertions(+), 144 deletions(-) create mode 100644 include/sbi_utils/timer/andes_plmt.h create mode 100644 lib/utils/timer/andes_plmt.c create mode 100644 lib/utils/timer/fdt_timer_plmt.c delete mode 100644 platform/andes/ae350/plmt.c delete mode 100644 platform/andes/ae350/plmt.h
include/sbi_utils/fdt/fdt_helper.h +3 -0
@@ -95,6 +95,9 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer, unsigned long *out_addr2, unsigned long *out_size2, u32 *out_first_hartid, u32 *out_hart_count); +int fdt_parse_plmt_node (void *fdt,int nodeoffset,unsigned long *plmt_base, +unsigned long *plmt_size,u32 *hart_count); +int fdt_parse_compat_addr (void *fdt,uint64_t *addr,const char *compatible);
include/sbi_utils/timer/andes_plmt.h new file +33 -0
@@ -0,0 +1,33 @@ +/* +* SPDX-License-Identifier: BSD-2-Clause +* +* Copyright (c) 2022 Andes Technology Corporation +* +* Authors: +* Zong Li <[email protected]> +* Nylon Chen <[email protected]> +* Yu Chien Peter Lin <[email protected]> +*/ + +#include <sbi/riscv_asm.h> +#include <sbi/riscv_io.h> +#include <sbi/sbi_timer.h> + +#ifndef __TIMER_ANDES_PLMT_H__ +#define __TIMER_ANDES_PLMT_H__ + +#define DEFAULT_AE350_PLMT_FREQ 60000000 +#define PLMT_REGION_ALIGN 0x1000 + +struct plmt_data { +u32 hart_count; +unsigned long size; +volatile u64 *time_val; +volatile u64 *time_cmp; +}; + +u64 plmt_timer_value (void ); +void plmt_timer_event_stop (void ); +void plmt_timer_event_start (u64 next_event); + +#endif /* __TIMER_ANDES_PLMT_H__ */
lib/utils/fdt/fdt_helper.c +54 -0
60 lines not on this page · raw message
lib/utils/timer/Kconfig +9 -0
@@ -14,10 +14,19 @@ config FDT_TIMER_MTIMER select TIMER_MTIMER default n +config FDT_TIMER_PLMT + bool "Andes PLMT FDT driver" + select TIMER_PLMT + default n + endif config TIMER_MTIMER bool "ACLINT MTIMER support" default n +config TIMER_PLMT + bool "Andes PLMT support" + default n + endmenu
lib/utils/timer/andes_plmt.c new file +54 -0
54 lines not on this page · raw message
lib/utils/timer/fdt_timer_plmt.c new file +79 -0
79 lines not on this page · raw message
lib/utils/timer/objects.mk +4 -0
@@ -8,9 +8,13 @@ # libsbiutils-objs-$(CONFIG_TIMER_MTIMER) += timer/aclint_mtimer.o +libsbiutils-objs-$(CONFIG_TIMER_PLMT) += timer/andes_plmt.o libsbiutils-objs-$(CONFIG_FDT_TIMER) += timer/fdt_timer.o libsbiutils-objs-$(CONFIG_FDT_TIMER) += timer/fdt_timer_drivers.o carray-fdt_timer_drivers-$(CONFIG_FDT_TIMER_MTIMER) += fdt_timer_mtimer libsbiutils-objs-$(CONFIG_FDT_TIMER_MTIMER) += timer/fdt_timer_mtimer.o + +carray-fdt_timer_drivers-$(CONFIG_FDT_TIMER_PLMT) += fdt_timer_plmt +libsbiutils-objs-$(CONFIG_FDT_TIMER_PLMT) += timer/fdt_timer_plmt.o
platform/andes/ae350/Kconfig +2 -0
@@ -6,6 +6,8 @@ config PLATFORM_ANDES_AE350 select IRQCHIP_PLIC select FDT_SERIAL select FDT_SERIAL_UART8250 + select FDT_TIMER + select FDT_TIMER_PLMT default y if PLATFORM_ANDES_AE350
platform/andes/ae350/objects.mk +1 -1
@@ -15,7 +15,7 @@ platform-asflags-y = platform-ldflags-y = # Objects to build -platform-objs-y += cache.o platform.o plicsw.o plmt.o +platform-objs-y += cache.o platform.o plicsw.o # Blobs to build FW_TEXT_START=0x00000000
platform/andes/ae350/platform.c +2 -17
@@ -19,9 +19,9 @@#include <sbi_utils/fdt/fdt_fixup.h> #include <sbi_utils/irqchip/plic.h> #include <sbi_utils/serial/fdt_serial.h> +#include <sbi_utils/timer/fdt_timer.h> #include "platform.h" #include "plicsw.h" -#include "plmt.h" #include "cache.h" static struct plic_data plic = {
@@ -81,21 +81,6 @@ static int ae350_ipi_init(bool cold_boot)return plicsw_warm_ipi_init (); } -/* Initialize platform timer for current HART. */ -static int ae350_timer_init (bool cold_boot) -{ -int ret; - -if (cold_boot) { - ret =plmt_cold_timer_init (AE350_PLMT_ADDR , -AE350_HART_COUNT ); -if (ret) -return ret; - } - -return plmt_warm_timer_init (); -} -/* Vendor-Specific SBI handler */ static int ae350_vendor_ext_provider(long extid, long funcid, const struct sbi_trap_regs *regs, unsigned long *out_value,
@@ -150,7 +135,7 @@ const struct sbi_platform_operations platform_ops = { .ipi_init = ae350_ipi_init, - .timer_init = ae350_timer_init, + .timer_init = fdt_timer_init, .vendor_ext_provider = ae350_vendor_ext_provider };
platform/andes/ae350/platform.h +0 -2
@@ -18,8 +18,6 @@#define AE350_PLICSW_ADDR 0xe6400000 -#define AE350_PLMT_ADDR 0xe6000000 -#define AE350_L2C_ADDR 0xe0500000/*Memory and Miscellaneous Registers*/
platform/andes/ae350/plmt.c deleted +0 -107
107 lines not on this page · raw message
platform/andes/ae350/plmt.h deleted +0 -17
@@ -1,17 +0,0 @@ -/* -* SPDX-License-Identifier: BSD-2-Clause -* -* Copyright (c) 2019 Andes Technology Corporation -* -* Authors: -* Zong Li <[email protected]> -*/ - -#ifndef _AE350_PLMT_H_ -#define _AE350_PLMT_H_ - -int plmt_warm_timer_init (void ); - -int plmt_cold_timer_init (unsigned long base,u32 hart_count); - -#endif /* _AE350_PLMT_H_ */
Signature · 1 line
2.34.1
PATCH v3 7/13 lib: utils/timer: Add Andes fdt timer support
Quoted 273 lines · Yu Chien Peter Lin
Since we can get the PLMT base address and timer frequency from device tree, move plmt timer device to fdt timer framework.
dts example (Quad-core AX45MP):
cpus { ... timebase-frequency = <0x3938700>; ... } soc { ... plmt0 at e6000000 { compatible = "andestech,plmt0"; reg = <0x00 0xe6000000 0x00 0x100000>; interrupts-extended = <&cpu0_intc 0x07 &cpu1_intc 0x07 &cpu2_intc 0x07 &cpu3_intc 0x07>; }; ... }Signed-off-by Yu Chien Peter Lin <[email protected]>Reviewed-by Anup Patel <[email protected]>---
Changes v2 -> v3
- Usesbi_domain_root_add_memrange()to add PLMT region to root domain--- include/sbi_utils/fdt/fdt_helper.h | 3 + include/sbi_utils/timer/andes_plmt.h | 33 +++++++++ lib/utils/fdt/fdt_helper.c | 54 ++++++++++++++ lib/utils/timer/Kconfig | 9 +++ lib/utils/timer/andes_plmt.c | 54 ++++++++++++++ lib/utils/timer/fdt_timer_plmt.c | 79 ++++++++++++++++++++ lib/utils/timer/objects.mk | 4 + platform/andes/ae350/Kconfig | 2 + platform/andes/ae350/objects.mk | 2 +- platform/andes/ae350/platform.c | 19 +---- platform/andes/ae350/platform.h | 2 - platform/andes/ae350/plmt.c | 107 --------------------------- platform/andes/ae350/plmt.h | 17 ----- 13 files changed, 241 insertions(+), 144 deletions(-) create mode 100644 include/sbi_utils/timer/andes_plmt.h create mode 100644 lib/utils/timer/andes_plmt.c create mode 100644 lib/utils/timer/fdt_timer_plmt.c delete mode 100644 platform/andes/ae350/plmt.c delete mode 100644 platform/andes/ae350/plmt.hinclude/sbi_utils/fdt/fdt_helper.h +3
-0@@ -95,6 +95,9 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer, unsigned long *out_addr2, unsigned long *out_size2, u32 *out_first_hartid, u32 *out_hart_count); +int fdt_parse_plmt_node (void *fdt,int nodeoffset,unsigned long *plmt_base, +unsigned long *plmt_size,u32 *hart_count); +int fdt_parse_compat_addr (void *fdt,uint64_t *addr,const char *compatible);include/sbi_utils/timer/andes_plmt.h new file +33
-0@@ -0,0 +1,33 @@ +/* +* SPDX-License-Identifier: BSD-2-Clause +* +* Copyright (c) 2022 Andes Technology Corporation +* +* Authors: +* Zong Li <[email protected]> +* Nylon Chen <[email protected]> +* Yu Chien Peter Lin <[email protected]> +*/ + +#include <sbi/riscv_asm.h> +#include <sbi/riscv_io.h> +#include <sbi/sbi_timer.h> + +#ifndef __TIMER_ANDES_PLMT_H__ +#define __TIMER_ANDES_PLMT_H__ + +#define DEFAULT_AE350_PLMT_FREQ 60000000 +#define PLMT_REGION_ALIGN 0x1000 + +struct plmt_data { +u32 hart_count; +unsigned long size; +volatile u64 *time_val; +volatile u64 *time_cmp; +}; + +u64 plmt_timer_value (void ); +void plmt_timer_event_stop (void ); +void plmt_timer_event_start (u64 next_event); + +#endif /* __TIMER_ANDES_PLMT_H__ */ lib/utils/fdt/fdt_helper.c +54
-0@@ -835,6 +835,60 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,return 0 ; } +int fdt_parse_plmt_node (void *fdt,int nodeoffset,unsigned long *plmt_base, +unsigned long *plmt_size,u32 *hart_count) +{ +const fdt32_t *val; +int rc, i, count; +uint64_t reg_addr, reg_size, cpu_offset, cpu_intc_offset; +u32 phandle, hwirq, hartid, hcount; + +if (nodeoffset <0 || !fdt || !plmt_base || + !hart_count || !plmt_size) +return SBI_EINVAL ; + + rc =fdt_get_node_addr_size (fdt, nodeoffset,0 , + ®_addr, ®_size); +if (rc <0 || !plmt_base || !plmt_size) +return SBI_ENODEV ; + *plmt_base = reg_addr; + *plmt_size = reg_size; + + val =fdt_getprop (fdt, nodeoffset,"interrupts-extended" , &count); +if (!val || count <sizeof (fdt32_t)) +return 0 ; + count = count /sizeof (fdt32_t); + + hcount =0 ; +for (i =0 ; i < (count /2 ); i++) { + phandle =fdt32_to_cpu (val[2 * i]); + hwirq =fdt32_to_cpu (val[2 * i +1 ]); + + cpu_intc_offset =fdt_node_offset_by_phandle (fdt, phandle); +if (cpu_intc_offset <0 ) +continue ; + + cpu_offset =fdt_parent_offset (fdt, cpu_intc_offset); +if (cpu_intc_offset <0 ) +continue ; + + rc =fdt_parse_hart_id (fdt, cpu_offset, &hartid); + +if (rc) +continue ; + +if (SBI_HARTMASK_MAX_BITS <= hartid) +continue ; + +if (hwirq ==IRQ_M_TIMER ) + hcount++; + } + + *hart_count = hcount; + +return 0 ; +} +int fdt_parse_compat_addr (void *fdt,uint64_t *addr,const char *compatible) {lib/utils/timer/Kconfig +9
-0@@ -14,10 +14,19 @@ config FDT_TIMER_MTIMER select TIMER_MTIMER default n +config FDT_TIMER_PLMT + bool "Andes PLMT FDT driver" + select TIMER_PLMT + default n + endif config TIMER_MTIMER bool "ACLINT MTIMER support" default n +config TIMER_PLMT + bool "Andes PLMT support" + default n + endmenulib/utils/timer/andes_plmt.c new file +54
-0@@ -0,0 +1,54 @@ +#include <sbi_utils/timer/andes_plmt.h> + +struct plmt_data plmt; + +u64 plmt_timer_value (void ) +{ +#if __riscv_xlen ==64 +return readq_relaxed (plmt.time_val); +#else +u32 lo, hi; + +do { + hi =readl_relaxed ((void *)plmt.time_val +0x04 ); + lo =readl_relaxed (plmt.time_val); + }while (hi !=readl_relaxed ((void *)plmt.time_val +0x04 )); + +return ((u64 )hi <<32 ) | (u64 )lo; +#endif +} + +void plmt_timer_event_stop (void ) +{ +u32 target_hart =current_hartid (); + +if (plmt.hart_count <= target_hart) +ebreak (); + +/* Clear PLMT Time Compare */ +#if __riscv_xlen ==64 +writeq_relaxed (-1ULL , &plmt.time_cmp[target_hart]); +#else +writel_relaxed (-1UL , &plmt.time_cmp[target_hart]); +writel_relaxed (-1UL , (void *)(&plmt.time_cmp[target_hart]) +0x04 ); +#endif +} + +void plmt_timer_event_start (u64 next_event) +{ +u32 target_hart =current_hartid (); + +if (plmt.hart_count <= target_hart) +ebreak (); + +/* Program PLMT Time Compare */ +#if __riscv_xlen ==64 +writeq_relaxed (next_event, &plmt.time_cmp[target_hart]); +#else +u32 mask =-1UL ; + +writel_relaxed (next_event & mask, &plmt.time_cmp[target_hart]); +writel_relaxed (next_event >>32 , + (void *)(&plmt.time_cmp[target_hart]) +0x04 ); +#endif +}lib/utils/timer/fdt_timer_plmt.c new file +15
-0@@ -0,0 +1,79 @@ +/* +* SPDX-License-Identifier: BSD-2-Clause +* +* Copyright (c) 2022 Andes Technology Corporation +* +* Authors: +* Yu Chien Peter Lin <[email protected]> +*/ + +#include <libfdt.h> +#include <sbi/sbi_error.h> +#include <sbi/sbi_domain.h> +#include <sbi_utils/fdt/fdt_helper.h> +#include <sbi_utils/timer/fdt_timer.h> +#include <sbi_utils/timer/andes_plmt.h>
lib/utils/timer/fdt_timer_plmt.c line 25
Quoted 10 lines
lib/utils/timer/fdt_timer_plmt.c new file +10
-0+ +extern struct plmt_data plmt; + +static struct sbi_timer_device plmt_timer = { + .name ="andes_plmt" , + .timer_freq =DEFAULT_AE350_PLMT_FREQ , + .timer_value = plmt_timer_value, + .timer_event_start = plmt_timer_event_start, + .timer_event_stop = plmt_timer_event_stop +};
Move plmt_timer to andes_plmt.c
Quoted 29 lines
lib/utils/timer/fdt_timer_plmt.c new file +29
-0+ +static int plmt_warm_timer_init (void ) +{ +if (!plmt.time_val) +return SBI_ENODEV ; + +plmt_timer_event_stop (); + +return 0 ; +} + +static int plmt_cold_timer_init (void *fdt,int nodeoff, +const struct fdt_match *match) +{ +int rc; +unsigned long freq, plmt_base; + + rc =fdt_parse_plmt_node (fdt, nodeoff, &plmt_base, &plmt.size, + &plmt.hart_count); +if (rc) +return rc; + + plmt.time_val = (u64 *)plmt_base; + plmt.time_cmp = (u64 *)(plmt_base +0x8 ); + + rc =fdt_parse_timebase_frequency (fdt, &freq); +if (rc) +return rc; +
lib/utils/timer/fdt_timer_plmt.c line 64
Quoted 10 lines
lib/utils/timer/fdt_timer_plmt.c new file +10
-0+ plmt_timer.timer_freq = freq; + +/* Add PLMT region to the root domain */ + rc =sbi_domain_root_add_memrange ( + plmt_base, plmt.size,PLMT_REGION_ALIGN , +SBI_DOMAIN_MEMREGION_MMIO |SBI_DOMAIN_MEMREGION_READABLE ); +if (rc) +return rc; + +sbi_timer_set_device (&plmt_timer);
Both sbi_domain_root_add_memrange() and sbi_timer_set_device() should be part of plmt_cold_timer_init() defined in andes_plmt.c
The plmt_cold_timer_init() in this file can be renamed to fdt_plmt_cold_timer_init() or something similar.
Quoted 255 lines
lib/utils/timer/fdt_timer_plmt.c new file +15
-0+ +return 0 ; +} + +static const struct fdt_match timer_plmt_match[] = { + { .compatible ="andestech,plmt0" }, + {}, +}; + +struct fdt_timer fdt_timer_plmt = { + .match_table = timer_plmt_match, + .cold_init = plmt_cold_timer_init, + .warm_init = plmt_warm_timer_init, + .exit =NULL , +};lib/utils/timer/objects.mk +4
-0@@ -8,9 +8,13 @@ # libsbiutils-objs-$(CONFIG_TIMER_MTIMER) += timer/aclint_mtimer.o +libsbiutils-objs-$(CONFIG_TIMER_PLMT) += timer/andes_plmt.o libsbiutils-objs-$(CONFIG_FDT_TIMER) += timer/fdt_timer.o libsbiutils-objs-$(CONFIG_FDT_TIMER) += timer/fdt_timer_drivers.o carray-fdt_timer_drivers-$(CONFIG_FDT_TIMER_MTIMER) += fdt_timer_mtimer libsbiutils-objs-$(CONFIG_FDT_TIMER_MTIMER) += timer/fdt_timer_mtimer.o + +carray-fdt_timer_drivers-$(CONFIG_FDT_TIMER_PLMT) += fdt_timer_plmt +libsbiutils-objs-$(CONFIG_FDT_TIMER_PLMT) += timer/fdt_timer_plmt.oplatform/andes/ae350/Kconfig +2
-0@@ -6,6 +6,8 @@ config PLATFORM_ANDES_AE350 select IRQCHIP_PLIC select FDT_SERIAL select FDT_SERIAL_UART8250 + select FDT_TIMER + select FDT_TIMER_PLMT default y if PLATFORM_ANDES_AE350platform/andes/ae350/objects.mk +1
-1@@ -15,7 +15,7 @@ platform-asflags-y = platform-ldflags-y = # Objects to build -platform-objs-y += cache.o platform.o plicsw.o plmt.o +platform-objs-y += cache.o platform.o plicsw.o # Blobs to build FW_TEXT_START=0x00000000platform/andes/ae350/platform.c +2
-17@@ -19,9 +19,9 @@#include <sbi_utils/fdt/fdt_fixup.h> #include <sbi_utils/irqchip/plic.h> #include <sbi_utils/serial/fdt_serial.h> +#include <sbi_utils/timer/fdt_timer.h> #include "platform.h" #include "plicsw.h" -#include "plmt.h" #include "cache.h" static struct plic_data plic = {@@ -81,21 +81,6 @@ static int ae350_ipi_init(bool cold_boot)return plicsw_warm_ipi_init (); } -/* Initialize platform timer for current HART. */ -static int ae350_timer_init (bool cold_boot) -{ -int ret; - -if (cold_boot) { - ret =plmt_cold_timer_init (AE350_PLMT_ADDR , -AE350_HART_COUNT ); -if (ret) -return ret; - } - -return plmt_warm_timer_init (); -} -/* Vendor-Specific SBI handler */ static int ae350_vendor_ext_provider(long extid, long funcid, const struct sbi_trap_regs *regs, unsigned long *out_value,@@ -150,7 +135,7 @@ const struct sbi_platform_operations platform_ops = { .ipi_init = ae350_ipi_init, - .timer_init = ae350_timer_init, + .timer_init = fdt_timer_init, .vendor_ext_provider = ae350_vendor_ext_provider };platform/andes/ae350/platform.h +0
-2@@ -18,8 +18,6 @@#define AE350_PLICSW_ADDR 0xe6400000 -#define AE350_PLMT_ADDR 0xe6000000 -#define AE350_L2C_ADDR 0xe0500000/*Memory and Miscellaneous Registers*/ platform/andes/ae350/plmt.c deleted +0
-107@@ -1,107 +0,0 @@ -/* -* SPDX-License-Identifier: BSD-2-Clause -* -* Copyright (c) 2019 Andes Technology Corporation -* -* Authors: -* Zong Li <[email protected]> -* Nylon Chen <[email protected]> -*/ - -#include <sbi/riscv_asm.h> -#include <sbi/riscv_io.h> -#include <sbi/sbi_timer.h> - -static u32 plmt_time_hart_count; -static volatile void *plmt_time_base; -static volatile u64 *plmt_time_val; -static volatile u64 *plmt_time_cmp; - -static u64 plmt_timer_value (void ) -{ -#if __riscv_xlen ==64 -return readq_relaxed (plmt_time_val); -#else -u32 lo, hi; - -do { - hi =readl_relaxed ((void *)plmt_time_val +0x04 ); - lo =readl_relaxed (plmt_time_val); - }while (hi !=readl_relaxed ((void *)plmt_time_val +0x04 )); - -return ((u64 )hi <<32 ) | (u64 )lo; -#endif -} - -static void plmt_timer_event_stop (void ) -{ -u32 target_hart =current_hartid (); - -if (plmt_time_hart_count <= target_hart) -return ; - -/* Clear PLMT Time Compare */ -#if __riscv_xlen ==64 -writeq_relaxed (-1ULL , &plmt_time_cmp[target_hart]); -#else -writel_relaxed (-1UL , &plmt_time_cmp[target_hart]); -writel_relaxed (-1UL , (void *)(&plmt_time_cmp[target_hart]) +0x04 ); -#endif -} - -static void plmt_timer_event_start (u64 next_event) -{ -u32 target_hart =current_hartid (); - -if (plmt_time_hart_count <= target_hart) -return ; - -/* Program PLMT Time Compare */ -#if __riscv_xlen ==64 -writeq_relaxed (next_event, &plmt_time_cmp[target_hart]); -#else -u32 mask =-1UL ; - -writel_relaxed (next_event & mask, &plmt_time_cmp[target_hart]); -writel_relaxed (next_event >>32 , - (void *)(&plmt_time_cmp[target_hart]) +0x04 ); -#endif - -} - -static struct sbi_timer_device plmt_timer = { - .name ="ae350_plmt" , - .timer_value = plmt_timer_value, - .timer_event_start = plmt_timer_event_start, - .timer_event_stop = plmt_timer_event_stop -}; - -int plmt_warm_timer_init (void ) -{ -u32 target_hart =current_hartid (); - -if (plmt_time_hart_count <= target_hart || !plmt_time_base) -return -1 ; - -/* Clear PLMT Time Compare */ -#if __riscv_xlen ==64 -writeq_relaxed (-1ULL , &plmt_time_cmp[target_hart]); -#else -writel_relaxed (-1UL , &plmt_time_cmp[target_hart]); -writel_relaxed (-1UL , (void *)(&plmt_time_cmp[target_hart]) +0x04 ); -#endif - -return 0 ; -} - -int plmt_cold_timer_init (unsigned long base,u32 hart_count) -{ - plmt_time_hart_count = hart_count; - plmt_time_base = (void *)base; - plmt_time_val = (u64 *)(plmt_time_base); - plmt_time_cmp = (u64 *)(plmt_time_base +0x8 ); - -sbi_timer_set_device (&plmt_timer); - -return 0 ; -}platform/andes/ae350/plmt.h deleted +0
-18@@ -1,17 +0,0 @@ -/* -* SPDX-License-Identifier: BSD-2-Clause -* -* Copyright (c) 2019 Andes Technology Corporation -* -* Authors: -* Zong Li <[email protected]> -*/ - -#ifndef _AE350_PLMT_H_ -#define _AE350_PLMT_H_ - -int plmt_warm_timer_init (void ); - -int plmt_cold_timer_init (unsigned long base,u32 hart_count); - -#endif /* _AE350_PLMT_H_ */ --
Quoted 2 lines
2.34.1
Regards,
Anup
PATCH v3 8/13 lib: utils/reset: Add Andes fdt reset driver support
In reply to Yu Chien Peter LinAdd ATCWDT200 as reset device of AE350 platform, this driver requires SMU to program the reset vector registers before triggering WDT software restart signal.
dts example:
smu at f0100000 {
compatible = "andestech,atcsmu";
reg = <0x00000000 0xf0100000 0x00000000 0x00001000>;
};
wdt: wdt at f0500000 {
compatible = "andestech,atcwdt200";
reg = <0x00000000 0xf0500000 0x00000000 0x00001000>;
interrupts = <3 4>;
interrupt-parent = <&plic0>;
clock-frequency = <15000000>;
};---
Changes v2 -> v3
- No change since v2
--- lib/utils/reset/Kconfig | 4 + lib/utils/reset/fdt_reset_atcwdt200.c | 122 ++++++++++++++++++++++++++ lib/utils/reset/objects.mk | 3 + platform/andes/ae350/Kconfig | 2 + platform/andes/ae350/platform.c | 3 + 5 files changed, 134 insertions(+) create mode 100644 lib/utils/reset/fdt_reset_atcwdt200.c
lib/utils/reset/Kconfig +4 -0
@@ -9,6 +9,10 @@ config FDT_RESET if FDT_RESET +config FDT_RESET_ATCWDT200 + bool "Andes WDT FDT reset driver" + default n + config FDT_RESET_GPIO bool "GPIO FDT reset driver" depends on FDT_GPIO
lib/utils/reset/fdt_reset_atcwdt200.c new file +122 -0
122 lines not on this page · raw message
lib/utils/reset/objects.mk +3 -0
@@ -10,6 +10,9 @@ libsbiutils-objs-$(CONFIG_FDT_RESET) += reset/fdt_reset.o libsbiutils-objs-$(CONFIG_FDT_RESET) += reset/fdt_reset_drivers.o +carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_ATCWDT200) += fdt_reset_atcwdt200 +libsbiutils-objs-$(CONFIG_FDT_RESET_ATCWDT200) += reset/fdt_reset_atcwdt200.o + carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_GPIO) += fdt_poweroff_gpio carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_GPIO) += fdt_reset_gpio libsbiutils-objs-$(CONFIG_FDT_RESET_GPIO) += reset/fdt_reset_gpio.o
platform/andes/ae350/Kconfig +2 -0
@@ -8,6 +8,8 @@ config PLATFORM_ANDES_AE350 select FDT_SERIAL_UART8250 select FDT_TIMER select FDT_TIMER_PLMT + select FDT_RESET + select FDT_RESET_ATCWDT200 default y if PLATFORM_ANDES_AE350
platform/andes/ae350/platform.c +3 -0
@@ -18,6 +18,7 @@#include <sbi_utils/fdt/fdt_helper.h> #include <sbi_utils/fdt/fdt_fixup.h> #include <sbi_utils/irqchip/plic.h> +#include <sbi_utils/reset/fdt_reset.h> #include <sbi_utils/serial/fdt_serial.h> #include <sbi_utils/timer/fdt_timer.h> #include "platform.h"
@@ -37,6 +38,8 @@ static int ae350_final_init(bool cold_boot)if (!cold_boot)return 0 ; +fdt_reset_init (); + fdt =fdt_get_address ();fdt_fixups (fdt);
Signature · 1 line
2.34.1
PATCH v3 9/13 platform: andes/ae350: Use fdt irqchip driver
In reply to Yu Chien Peter LinAndes PLIC is compatible with plic driver. The PLIC base address and number of source can be obtained by parsing the device tree.
---
Changes v2 -> v3
- No change since v2
--- platform/andes/ae350/Kconfig | 3 ++- platform/andes/ae350/platform.c | 24 ++---------------------- platform/andes/ae350/platform.h | 3 --- 3 files changed, 4 insertions(+), 26 deletions(-)
platform/andes/ae350/Kconfig +2 -1
@@ -3,13 +3,14 @@ config PLATFORM_ANDES_AE350 bool select FDT - select IRQCHIP_PLIC select FDT_SERIAL select FDT_SERIAL_UART8250 select FDT_TIMER select FDT_TIMER_PLMT select FDT_RESET select FDT_RESET_ATCWDT200 + select FDT_IRQCHIP + select FDT_IRQCHIP_PLIC default y if PLATFORM_ANDES_AE350
platform/andes/ae350/platform.c +2 -22
@@ -17,7 +17,7 @@#include <sbi/sbi_trap.h> #include <sbi_utils/fdt/fdt_helper.h> #include <sbi_utils/fdt/fdt_fixup.h> -#include <sbi_utils/irqchip/plic.h> +#include <sbi_utils/irqchip/fdt_irqchip.h> #include <sbi_utils/reset/fdt_reset.h> #include <sbi_utils/serial/fdt_serial.h> #include <sbi_utils/timer/fdt_timer.h>
@@ -25,11 +25,6 @@#include "plicsw.h" #include "cache.h" -static struct plic_data plic = { - .addr =AE350_PLIC_ADDR , - .num_src =AE350_PLIC_NUM_SOURCES , -}; -/* Platform final initialization. */ static int ae350_final_init (bool cold_boot) {
@@ -46,21 +41,6 @@ static int ae350_final_init(bool cold_boot)return 0 ; } -/* Initialize the platform interrupt controller for current HART. */ -static int ae350_irqchip_init (bool cold_boot) -{ -u32 hartid =current_hartid (); -int ret; - -if (cold_boot) { - ret =plic_cold_irqchip_init (&plic); -if (ret) -return ret; - } - -return plic_warm_irqchip_init (&plic,2 * hartid,2 * hartid +1 ); -} -static struct sbi_ipi_device plicsw_ipi = { .name ="ae350_plicsw" , .ipi_send = plicsw_ipi_send,
@@ -134,7 +114,7 @@ const struct sbi_platform_operations platform_ops = { .console_init = fdt_serial_init, - .irqchip_init = ae350_irqchip_init, + .irqchip_init = fdt_irqchip_init, .ipi_init = ae350_ipi_init,
platform/andes/ae350/platform.h +0 -3
@@ -13,9 +13,6 @@#define AE350_HART_COUNT 4 -#define AE350_PLIC_ADDR 0xe4000000 -#define AE350_PLIC_NUM_SOURCES 71 -#define AE350_PLICSW_ADDR 0xe6400000#define AE350_L2C_ADDR 0xe0500000
Signature · 1 line
2.34.1
PATCH v3 10/13 platform: andes/ae350: Add fw_platform_init for platform initialization
In reply to Yu Chien Peter LinThis patch adds fw_platform_init() to initialize ae350 platform.name and platform.hart_count by parsing device tree.
---
Changes v2 -> v3
- No change since v2
--- platform/andes/ae350/platform.c | 51 +++++++++++++++++++++++++++++++-- platform/andes/ae350/platform.h | 2 -- 2 files changed, 49 insertions(+), 4 deletions(-)
platform/andes/ae350/platform.c +49 -2
@@ -6,14 +6,18 @@* Authors: * Zong Li <[email protected]> * Nylon Chen <[email protected]> +* Yu Chien Peter Lin <[email protected]> */ +#include <libfdt.h> #include <sbi/riscv_asm.h> #include <sbi/riscv_encoding.h> #include <sbi/sbi_console.h> #include <sbi/sbi_const.h> +#include <sbi/sbi_hartmask.h> #include <sbi/sbi_ipi.h> #include <sbi/sbi_platform.h> +#include <sbi/sbi_string.h> #include <sbi/sbi_trap.h> #include <sbi_utils/fdt/fdt_helper.h> #include <sbi_utils/fdt/fdt_fixup.h>
@@ -25,6 +29,49 @@#include "plicsw.h" #include "cache.h" +struct sbi_platform platform; +unsigned long fw_platform_init (unsigned long arg0,unsigned long arg1, +unsigned long arg2,unsigned long arg3, +unsigned long arg4) +{ +const char *model; +void *fdt = (void *)arg1; +u32 hartid, hart_count =0 ; +int rc, root_offset, cpus_offset, cpu_offset, len; + + root_offset =fdt_path_offset (fdt,"/" ); +if (root_offset <0 ) + goto fail; + + model =fdt_getprop (fdt, root_offset,"model" , &len); +if (model) +sbi_strncpy (platform.name, model,sizeof (platform.name) -1 ); + + cpus_offset =fdt_path_offset (fdt,"/cpus" ); +if (cpus_offset <0 ) + goto fail; + +fdt_for_each_subnode (cpu_offset, fdt, cpus_offset) { + rc =fdt_parse_hart_id (fdt, cpu_offset, &hartid); +if (rc) +continue ; + +if (SBI_HARTMASK_MAX_BITS <= hartid) +continue ; + + hart_count++; + } + + platform.hart_count = hart_count; + +/* Return original FDT pointer */ +return arg1; + +fail: +while (1 ) +wfi (); +} +/* Platform final initialization. */ static int ae350_final_init (bool cold_boot) {
@@ -123,14 +170,14 @@ const struct sbi_platform_operations platform_ops = { .vendor_ext_provider = ae350_vendor_ext_provider }; -const struct sbi_platform platform = { +struct sbi_platform platform = { .opensbi_version =OPENSBI_VERSION , .platform_version =SBI_PLATFORM_VERSION (CONFIG_PLATFORM_ANDES_AE350_MAJOR_VER ,CONFIG_PLATFORM_ANDES_AE350_MINOR_VER ), .name =CONFIG_PLATFORM_ANDES_AE350_NAME , .features =SBI_PLATFORM_DEFAULT_FEATURES , - .hart_count =AE350_HART_COUNT , + .hart_count =SBI_HARTMASK_MAX_BITS , .hart_stack_size =SBI_PLATFORM_DEFAULT_HART_STACK_SIZE , .platform_ops_addr = (unsigned long )&platform_ops };
platform/andes/ae350/platform.h +0 -2
@@ -11,8 +11,6 @@#ifndef _AE350_PLATFORM_H_#define _AE350_PLATFORM_H_ -#define AE350_HART_COUNT 4 -#define AE350_PLICSW_ADDR 0xe6400000#define AE350_L2C_ADDR 0xe0500000
Signature · 1 line
2.34.1
PATCH v3 11/13 lib: utils/ipi: Add Andes fdt ipi driver support
In reply to Yu Chien Peter LinMove Andes PLICSW ipi device to fdt ipi framework, this patch is based on Leo's modified IPI scheme on PLICSW.
Current IPI scheme uses bit 0 of pending reigster on PLICSW to send IPI from hart 0 to hart 7, but bit 0 needs to be hardwired to 0 according to spec. After some investigation, self-IPI seems to be seldom or never used, so we re-order the IPI scheme to support 8 core platforms.
dts example (Quad-core AX45MP):
plicsw: interrupt-controller at e6400000 {
compatible = "andestech,plicsw";
reg = <0x00000000 0xe6400000 0x00000000 0x00400000>;
interrupts-extended = <&CPU0_intc 3
&CPU1_intc 3
&CPU2_intc 3
&CPU3_intc 3>;
interrupt-controller;
#address-cells = <2>;
#interrupt-cells = <2>;
};---
Changes v2 -> v3
- Remove "riscv,ndev" from plicsw device tree node and drop "num_src"
- Use sbi_domain_root_add_memrange() to add PLICSW region to root domain
--- include/sbi_utils/fdt/fdt_helper.h | 3 + include/sbi_utils/ipi/andes_plicsw.h | 49 ++++++++++ lib/utils/fdt/fdt_helper.c | 55 +++++++++++ lib/utils/ipi/Kconfig | 9 ++ lib/utils/ipi/andes_plicsw.c | 85 ++++++++++++++++ lib/utils/ipi/fdt_ipi_plicsw.c | 87 +++++++++++++++++ lib/utils/ipi/objects.mk | 4 + platform/andes/ae350/Kconfig | 2 + platform/andes/ae350/objects.mk | 2 +- platform/andes/ae350/platform.c | 27 +----- platform/andes/ae350/platform.h | 2 - platform/andes/ae350/plicsw.c | 139 --------------------------- platform/andes/ae350/plicsw.h | 44 --------- 13 files changed, 297 insertions(+), 211 deletions(-) create mode 100644 include/sbi_utils/ipi/andes_plicsw.h create mode 100644 lib/utils/ipi/andes_plicsw.c create mode 100644 lib/utils/ipi/fdt_ipi_plicsw.c delete mode 100644 platform/andes/ae350/plicsw.c delete mode 100644 platform/andes/ae350/plicsw.h
include/sbi_utils/fdt/fdt_helper.h +3 -0
@@ -98,6 +98,9 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,int fdt_parse_plmt_node (void *fdt,int nodeoffset,unsigned long *plmt_base,unsigned long *plmt_size,u32 *hart_count); +int fdt_parse_plicsw_node (void *fdt,int nodeoffset,unsigned long *plicsw_base, +unsigned long *size,u32 *hart_count); +int fdt_parse_compat_addr (void *fdt,uint64_t *addr,const char *compatible);
include/sbi_utils/ipi/andes_plicsw.h new file +49 -0
49 lines not on this page · raw message
lib/utils/fdt/fdt_helper.c +55 -0
61 lines not on this page · raw message
lib/utils/ipi/Kconfig +9 -0
@@ -14,10 +14,19 @@ config FDT_IPI_MSWI select IPI_MSWI default n +config FDT_IPI_PLICSW + bool "Andes PLICSW FDT driver" + select IPI_PLICSW + default n + endif config IPI_MSWI bool "ACLINT MSWI support" default n +config IPI_PLICSW + bool "Andes PLICSW support" + default n + endmenu
lib/utils/ipi/andes_plicsw.c new file +85 -0
85 lines not on this page · raw message
lib/utils/ipi/fdt_ipi_plicsw.c new file +87 -0
87 lines not on this page · raw message
lib/utils/ipi/objects.mk +4 -0
@@ -8,9 +8,13 @@ # libsbiutils-objs-$(CONFIG_IPI_MSWI) += ipi/aclint_mswi.o +libsbiutils-objs-$(CONFIG_IPI_PLICSW) += ipi/andes_plicsw.o libsbiutils-objs-$(CONFIG_FDT_IPI) += ipi/fdt_ipi.o libsbiutils-objs-$(CONFIG_FDT_IPI) += ipi/fdt_ipi_drivers.o carray-fdt_ipi_drivers-$(CONFIG_FDT_IPI_MSWI) += fdt_ipi_mswi libsbiutils-objs-$(CONFIG_FDT_IPI_MSWI) += ipi/fdt_ipi_mswi.o + +carray-fdt_ipi_drivers-$(CONFIG_FDT_IPI_PLICSW) += fdt_ipi_plicsw +libsbiutils-objs-$(CONFIG_FDT_IPI_PLICSW) += ipi/fdt_ipi_plicsw.o
platform/andes/ae350/Kconfig +2 -0
@@ -11,6 +11,8 @@ config PLATFORM_ANDES_AE350 select FDT_RESET_ATCWDT200 select FDT_IRQCHIP select FDT_IRQCHIP_PLIC + select FDT_IPI + select FDT_IPI_PLICSW default y if PLATFORM_ANDES_AE350
platform/andes/ae350/objects.mk +1 -1
@@ -15,7 +15,7 @@ platform-asflags-y = platform-ldflags-y = # Objects to build -platform-objs-y += cache.o platform.o plicsw.o +platform-objs-y += cache.o platform.o # Blobs to build FW_TEXT_START=0x00000000
platform/andes/ae350/platform.c +2 -25
@@ -25,8 +25,8 @@#include <sbi_utils/reset/fdt_reset.h> #include <sbi_utils/serial/fdt_serial.h> #include <sbi_utils/timer/fdt_timer.h> +#include <sbi_utils/ipi/fdt_ipi.h> #include "platform.h" -#include "plicsw.h" #include "cache.h" struct sbi_platform platform;
@@ -88,29 +88,6 @@ static int ae350_final_init(bool cold_boot)return 0 ; } -static struct sbi_ipi_device plicsw_ipi = { - .name ="ae350_plicsw" , - .ipi_send = plicsw_ipi_send, - .ipi_clear = plicsw_ipi_clear -}; - -/* Initialize IPI for current HART. */ -static int ae350_ipi_init (bool cold_boot) -{ -int ret; - -if (cold_boot) { - ret =plicsw_cold_ipi_init (AE350_PLICSW_ADDR , -AE350_HART_COUNT ); -if (ret) -return ret; - -sbi_ipi_set_device (&plicsw_ipi); - } - -return plicsw_warm_ipi_init (); -} -/* Vendor-Specific SBI handler */ static int ae350_vendor_ext_provider(long extid, long funcid, const struct sbi_trap_regs *regs, unsigned long *out_value,
@@ -163,7 +140,7 @@ const struct sbi_platform_operations platform_ops = { .irqchip_init = fdt_irqchip_init, - .ipi_init = ae350_ipi_init, + .ipi_init = fdt_ipi_init, .timer_init = fdt_timer_init,
platform/andes/ae350/platform.h +0 -2
@@ -11,8 +11,6 @@#ifndef _AE350_PLATFORM_H_#define _AE350_PLATFORM_H_ -#define AE350_PLICSW_ADDR 0xe6400000 -#define AE350_L2C_ADDR 0xe0500000/*Memory and Miscellaneous Registers*/
platform/andes/ae350/plicsw.c deleted +0 -139
139 lines not on this page · raw message
platform/andes/ae350/plicsw.h deleted +0 -44
44 lines not on this page · raw message
Signature · 1 line
2.34.1
PATCH v3 11/13 lib: utils/ipi: Add Andes fdt ipi driver support
Quoted 171 lines · Yu Chien Peter Lin
Move Andes PLICSW ipi device to fdt ipi framework, this patch is based on Leo's modified IPI scheme on PLICSW.
Current IPI scheme uses bit 0 of pending reigster on PLICSW to send IPI from hart 0 to hart 7, but bit 0 needs to be hardwired to 0 according to spec. After some investigation, self-IPI seems to be seldom or never used, so we re-order the IPI scheme to support 8 core platforms.
dts example (Quad-core AX45MP):
plicsw: interrupt-controller at e6400000 { compatible = "andestech,plicsw"; reg = <0x00000000 0xe6400000 0x00000000 0x00400000>; interrupts-extended = <&CPU0_intc 3 &CPU1_intc 3 &CPU2_intc 3 &CPU3_intc 3>; interrupt-controller; #address-cells = <2>; #interrupt-cells = <2>; };Signed-off-by Yu Chien Peter Lin <[email protected]>---
Changes v2 -> v3
- Remove "riscv,ndev" from plicsw device tree node and drop "num_src"
- Usesbi_domain_root_add_memrange()to add PLICSW region to root domain--- include/sbi_utils/fdt/fdt_helper.h | 3 + include/sbi_utils/ipi/andes_plicsw.h | 49 ++++++++++ lib/utils/fdt/fdt_helper.c | 55 +++++++++++ lib/utils/ipi/Kconfig | 9 ++ lib/utils/ipi/andes_plicsw.c | 85 ++++++++++++++++ lib/utils/ipi/fdt_ipi_plicsw.c | 87 +++++++++++++++++ lib/utils/ipi/objects.mk | 4 + platform/andes/ae350/Kconfig | 2 + platform/andes/ae350/objects.mk | 2 +- platform/andes/ae350/platform.c | 27 +----- platform/andes/ae350/platform.h | 2 - platform/andes/ae350/plicsw.c | 139 --------------------------- platform/andes/ae350/plicsw.h | 44 --------- 13 files changed, 297 insertions(+), 211 deletions(-) create mode 100644 include/sbi_utils/ipi/andes_plicsw.h create mode 100644 lib/utils/ipi/andes_plicsw.c create mode 100644 lib/utils/ipi/fdt_ipi_plicsw.c delete mode 100644 platform/andes/ae350/plicsw.c delete mode 100644 platform/andes/ae350/plicsw.hinclude/sbi_utils/fdt/fdt_helper.h +3
-0@@ -98,6 +98,9 @@ int fdt_parse_aclint_node(void *fdt, int nodeoffset, bool for_timer,int fdt_parse_plmt_node (void *fdt,int nodeoffset,unsigned long *plmt_base,unsigned long *plmt_size,u32 *hart_count); +int fdt_parse_plicsw_node (void *fdt,int nodeoffset,unsigned long *plicsw_base, +unsigned long *size,u32 *hart_count); +int fdt_parse_compat_addr (void *fdt,uint64_t *addr,const char *compatible);include/sbi_utils/ipi/andes_plicsw.h new file +49
-0@@ -0,0 +1,49 @@ +/* +* SPDX-License-Identifier: BSD-2-Clause +* +* Copyright (c) 2022 Andes Technology Corporation +* +* Authors: +* Zong Li <[email protected]> +* Nylon Chen <[email protected]> +* Leo Yu-Chi Liang <[email protected]> +* Yu Chien Peter Lin <[email protected]> +*/ + +#include <sbi/riscv_asm.h> +#include <sbi/riscv_io.h> +#include <sbi/sbi_types.h> + +#ifndef _IPI_ANDES_PLICSW_H_ +#define _IPI_ANDES_PLICSW_H_ + +#define PLICSW_PRIORITY_BASE 0x4 + +#define PLICSW_PENDING_BASE 0x1000 +#define PLICSW_PENDING_STRIDE 0x8 + +#define PLICSW_ENABLE_BASE 0x2000 +#define PLICSW_ENABLE_STRIDE 0x80 + +#define PLICSW_CONTEXT_BASE 0x200000 +#define PLICSW_CONTEXT_STRIDE 0x1000 +#define PLICSW_CONTEXT_CLAIM 0x4 + +#define PLICSW_HART_MASK 0x01010101 + +#define PLICSW_HART_MAX_NR 8 + +#define PLICSW_REGION_ALIGN 0x1000 + +struct plicsw_data { +unsigned long addr; +unsigned long size; +uint32_t hart_count; +/* hart id to source id table */ +uint32_t source_id[PLICSW_HART_MAX_NR ]; +}; + +void plicsw_ipi_send (u32 target_hart); +void plicsw_ipi_clear (u32 target_hart); + +#endif /* _IPI_ANDES_PLICSW_H_ */ lib/utils/fdt/fdt_helper.c +45
-0@@ -889,6 +889,61 @@ int fdt_parse_plmt_node(void *fdt, int nodeoffset, unsigned long *plmt_base,return 0 ; } +int fdt_parse_plicsw_node (void *fdt,int nodeoffset,unsigned long *plicsw_base, +unsigned long *size,u32 *hart_count) +{ +const fdt32_t *val; +int rc, i, count; +uint64_t reg_addr, reg_size, cpu_offset, cpu_intc_offset; +u32 phandle, hwirq, hartid, hcount; + +if (nodeoffset <0 || !fdt || !plicsw_base || + !hart_count || !size) +return SBI_EINVAL ; + + rc =fdt_get_node_addr_size (fdt, nodeoffset,0 , + ®_addr, ®_size); +if (rc <0 || !plicsw_base || !size) +return SBI_ENODEV ; + *plicsw_base = reg_addr; + *size = reg_size; + + val =fdt_getprop (fdt, nodeoffset,"interrupts-extended" , &count); +if (!val || count <sizeof (fdt32_t)) +return 0 ; + count = count /sizeof (fdt32_t); + + hcount =0 ; +for (i =0 ; i < (count /2 ); i++) { + phandle =fdt32_to_cpu (val[2 * i]); + hwirq =fdt32_to_cpu (val[2 * i +1 ]); + + cpu_intc_offset =fdt_node_offset_by_phandle (fdt, phandle); +if (cpu_intc_offset <0 ) +continue ; + + cpu_offset =fdt_parent_offset (fdt, cpu_intc_offset); +if (cpu_intc_offset <0 ) +continue ; + + rc =fdt_parse_hart_id (fdt, cpu_offset, &hartid); + +if (rc) +continue ; + +if (SBI_HARTMASK_MAX_BITS <= hartid) +continue ; +
lib/utils/fdt/fdt_helper.c int fdt_parse_plmt_node(void *fdt, int nodeoffset, unsigned long *plmt_base, · line 946
Quoted 10 lines
lib/utils/fdt/fdt_helper.c +10
-0+if (hwirq ==IRQ_M_SOFT ) + hcount++; + } + + *hart_count = hcount; + +return 0 ; +} + +
Drop the extra newline from here.
Quoted 140 lines
lib/utils/fdt/fdt_helper.c +0
-0int fdt_parse_compat_addr (void *fdt,uint64_t *addr,const char *compatible) {lib/utils/ipi/Kconfig +9
-0@@ -14,10 +14,19 @@ config FDT_IPI_MSWI select IPI_MSWI default n +config FDT_IPI_PLICSW + bool "Andes PLICSW FDT driver" + select IPI_PLICSW + default n + endif config IPI_MSWI bool "ACLINT MSWI support" default n +config IPI_PLICSW + bool "Andes PLICSW support" + default n + endmenulib/utils/ipi/andes_plicsw.c new file +85
-0@@ -0,0 +1,85 @@ +/* +* SPDX-License-Identifier: BSD-2-Clause +* +* Copyright (c) 2022 Andes Technology Corporation +* +* Authors: +* Zong Li <[email protected]> +* Nylon Chen <[email protected]> +* Leo Yu-Chi Liang <[email protected]> +* Yu Chien Peter Lin <[email protected]> +*/ + +#include <sbi/sbi_types.h> +#include <sbi_utils/ipi/andes_plicsw.h> + +extern struct plicsw_data plicsw; + +static inline void plicsw_claim (void ) +{ +u32 hartid =current_hartid (); + +if (plicsw.hart_count <= hartid) +ebreak (); + + plicsw.source_id[hartid] = +readl ((void *)plicsw.addr +PLICSW_CONTEXT_BASE + +PLICSW_CONTEXT_CLAIM +PLICSW_CONTEXT_STRIDE * hartid); +} + +static inline void plicsw_complete (void ) +{ +u32 hartid =current_hartid (); +u32 source = plicsw.source_id[hartid]; + +writel (source, (void *)plicsw.addr +PLICSW_CONTEXT_BASE + +PLICSW_CONTEXT_CLAIM + +PLICSW_CONTEXT_STRIDE * hartid); +} + +static inline void plic_sw_pending (u32 target_hart) +{ +/* +* The pending array registers are w1s type. +* IPI pending array mapping as following: +* +* Pending array start address: base + 0x1000 +* --------------------------------- +* | hart3 | hart2 | hart1 | hart0 | +* --------------------------------- +* Each hartX can send IPI to another hart by setting the +* bitY to its own region (see the below). +* +* In each hartX region: +* <---------- PICSW_PENDING_STRIDE --------> +* | bit7 | ... | bit3 | bit2 | bit1 | bit0 | +* ------------------------------------------ +* The bitY of hartX region indicates that hartX sends an +* IPI to hartY. +*/ +u32 hartid =current_hartid (); +u32 word_index = hartid /4 ; +u32 per_hart_offset =PLICSW_PENDING_STRIDE * hartid; +u32 val =1 << target_hart << per_hart_offset; + +writel (val, (void *)plicsw.addr +PLICSW_PENDING_BASE + word_index *4 ); +} + +void plicsw_ipi_send (u32 target_hart) +{ +if (plicsw.hart_count <= target_hart) +ebreak (); + +/* Set PLICSW IPI */ +plic_sw_pending (target_hart); +} + +void plicsw_ipi_clear (u32 target_hart) +{ +if (plicsw.hart_count <= target_hart) +ebreak (); + +/* Clear PLICSW IPI */ +plicsw_claim (); +plicsw_complete (); +}lib/utils/ipi/fdt_ipi_plicsw.c new file +16
-0@@ -0,0 +1,87 @@ +/* +* SPDX-License-Identifier: BSD-2-Clause +* +* Copyright (c) 2022 Andes Technology Corporation +* +* Authors: +* Zong Li <[email protected]> +* Nylon Chen <[email protected]> +* Leo Yu-Chi Liang <[email protected]> +* Yu Chien Peter Lin <[email protected]> +*/ + +#include <sbi/sbi_domain.h> +#include <sbi/sbi_error.h> +#include <sbi/sbi_ipi.h> +#include <sbi_utils/fdt/fdt_helper.h>
lib/utils/ipi/fdt_ipi_plicsw.c line 26
Quoted 10 lines
lib/utils/ipi/fdt_ipi_plicsw.c new file +10
-0+#include <sbi_utils/ipi/fdt_ipi.h> +#include <sbi_utils/ipi/andes_plicsw.h> + +struct plicsw_data plicsw; + +static struct sbi_ipi_device plicsw_ipi = { + .name ="andes_plicsw" , + .ipi_send = plicsw_ipi_send, + .ipi_clear = plicsw_ipi_clear +};
Move both of the above to andes_plicsw.c
Quoted 36 lines
lib/utils/ipi/fdt_ipi_plicsw.c new file +36
-0+ +static int plicsw_warm_ipi_init (void ) +{ +u32 hartid =current_hartid (); + +/* Clear PLICSW IPI */ +plicsw_ipi_clear (hartid); + +return 0 ; +} + +static int plicsw_cold_ipi_init (void *fdt,int nodeoff, +const struct fdt_match *match) +{ +int rc; + + rc =fdt_parse_plicsw_node (fdt, nodeoff, &plicsw.addr, &plicsw.size, + &plicsw.hart_count); +if (rc) +return rc; + +/* Setup source priority */ +uint32_t *priority = (void *)plicsw.addr +PLICSW_PRIORITY_BASE ; + +for (int i =0 ; i < plicsw.hart_count; i++) +writel (1 , &priority[i]); + +/* Setup target enable */ +uint32_t enable_mask =PLICSW_HART_MASK ; + +for (int i =0 ; i < plicsw.hart_count; i++) { +uint32_t *enable = (void *)plicsw.addr +PLICSW_ENABLE_BASE + +PLICSW_ENABLE_STRIDE * i; +writel (enable_mask, enable); +writel (enable_mask, enable +1 ); + enable_mask <<=1 ;
lib/utils/ipi/fdt_ipi_plicsw.c line 72
Quoted 10 lines
lib/utils/ipi/fdt_ipi_plicsw.c new file +10
-0+ } + +/* Add PLICSW region to the root domain */ + rc =sbi_domain_root_add_memrange (plicsw.addr, plicsw.size, +PLICSW_REGION_ALIGN , +SBI_DOMAIN_MEMREGION_MMIO ); +if (rc) +return rc; + +sbi_ipi_set_device (&plicsw_ipi);
Both sbi_domain_root_add_memrange() and sbi_ipi_set_device() should be done by plicsw_cold_ipi_init() defined in andes_plicsw.c
The plicsw_cold_ipi_init() over here can be renamed to fdt_plicsw_cold_ipi_init() or something similar.
Quoted 324 lines
lib/utils/ipi/fdt_ipi_plicsw.c new file +15
-0+ +return 0 ; +} + +static const struct fdt_match ipi_plicsw_match[] = { + { .compatible ="andestech,plicsw" }, + {}, +}; + +struct fdt_ipi fdt_ipi_plicsw = { + .match_table = ipi_plicsw_match, + .cold_init = plicsw_cold_ipi_init, + .warm_init = plicsw_warm_ipi_init, + .exit =NULL , +};lib/utils/ipi/objects.mk +4
-0@@ -8,9 +8,13 @@ # libsbiutils-objs-$(CONFIG_IPI_MSWI) += ipi/aclint_mswi.o +libsbiutils-objs-$(CONFIG_IPI_PLICSW) += ipi/andes_plicsw.o libsbiutils-objs-$(CONFIG_FDT_IPI) += ipi/fdt_ipi.o libsbiutils-objs-$(CONFIG_FDT_IPI) += ipi/fdt_ipi_drivers.o carray-fdt_ipi_drivers-$(CONFIG_FDT_IPI_MSWI) += fdt_ipi_mswi libsbiutils-objs-$(CONFIG_FDT_IPI_MSWI) += ipi/fdt_ipi_mswi.o + +carray-fdt_ipi_drivers-$(CONFIG_FDT_IPI_PLICSW) += fdt_ipi_plicsw +libsbiutils-objs-$(CONFIG_FDT_IPI_PLICSW) += ipi/fdt_ipi_plicsw.oplatform/andes/ae350/Kconfig +2
-0@@ -11,6 +11,8 @@ config PLATFORM_ANDES_AE350 select FDT_RESET_ATCWDT200 select FDT_IRQCHIP select FDT_IRQCHIP_PLIC + select FDT_IPI + select FDT_IPI_PLICSW default y if PLATFORM_ANDES_AE350platform/andes/ae350/objects.mk +1
-1@@ -15,7 +15,7 @@ platform-asflags-y = platform-ldflags-y = # Objects to build -platform-objs-y += cache.o platform.o plicsw.o +platform-objs-y += cache.o platform.o # Blobs to build FW_TEXT_START=0x00000000platform/andes/ae350/platform.c +2
-25@@ -25,8 +25,8 @@#include <sbi_utils/reset/fdt_reset.h> #include <sbi_utils/serial/fdt_serial.h> #include <sbi_utils/timer/fdt_timer.h> +#include <sbi_utils/ipi/fdt_ipi.h> #include "platform.h" -#include "plicsw.h" #include "cache.h" struct sbi_platform platform;@@ -88,29 +88,6 @@ static int ae350_final_init(bool cold_boot)return 0 ; } -static struct sbi_ipi_device plicsw_ipi = { - .name ="ae350_plicsw" , - .ipi_send = plicsw_ipi_send, - .ipi_clear = plicsw_ipi_clear -}; - -/* Initialize IPI for current HART. */ -static int ae350_ipi_init (bool cold_boot) -{ -int ret; - -if (cold_boot) { - ret =plicsw_cold_ipi_init (AE350_PLICSW_ADDR , -AE350_HART_COUNT ); -if (ret) -return ret; - -sbi_ipi_set_device (&plicsw_ipi); - } - -return plicsw_warm_ipi_init (); -} -/* Vendor-Specific SBI handler */ static int ae350_vendor_ext_provider(long extid, long funcid, const struct sbi_trap_regs *regs, unsigned long *out_value,@@ -163,7 +140,7 @@ const struct sbi_platform_operations platform_ops = { .irqchip_init = fdt_irqchip_init, - .ipi_init = ae350_ipi_init, + .ipi_init = fdt_ipi_init, .timer_init = fdt_timer_init,platform/andes/ae350/platform.h +0
-2@@ -11,8 +11,6 @@#ifndef _AE350_PLATFORM_H_#define _AE350_PLATFORM_H_ -#define AE350_PLICSW_ADDR 0xe6400000 -#define AE350_L2C_ADDR 0xe0500000/*Memory and Miscellaneous Registers*/ platform/andes/ae350/plicsw.c deleted +0
-139@@ -1,139 +0,0 @@ -/* -* SPDX-License-Identifier: BSD-2-Clause -* -* Copyright (c) 2019 Andes Technology Corporation -* -* Authors: -* Zong Li <[email protected]> -* Nylon Chen <[email protected]> -*/ - -#include <sbi/riscv_asm.h> -#include <sbi/riscv_io.h> -#include <sbi/sbi_types.h> -#include "plicsw.h" -#include "platform.h" - -static u32 plicsw_ipi_hart_count; -static struct plicsw plicsw_dev[AE350_HART_COUNT ]; - -static inline void plicsw_claim (void ) -{ -u32 source_hart =current_hartid (); - - plicsw_dev[source_hart].source_id = -readl (plicsw_dev[source_hart].plicsw_claim); -} - -static inline void plicsw_complete (void ) -{ -u32 source_hart =current_hartid (); -u32 source = plicsw_dev[source_hart].source_id; - -writel (source, plicsw_dev[source_hart].plicsw_claim); -} - -static inline void plic_sw_pending (u32 target_hart) -{ -/* -* The pending array registers are w1s type. -* IPI pending array mapping as following: -* -* Pending array start address: base + 0x1000 -* ------------------------------------- -* | hart 3 | hart 2 | hart 1 | hart 0 | -* ------------------------------------- -* Each hart X can send IPI to another hart by setting the -* corresponding bit in hart X own region(see the below). -* -* In each hart region: -* ----------------------------------------------- -* | bit 7 | bit 6 | bit 5 | bit 4 | ... | bit 0 | -* ----------------------------------------------- -* The bit 7 is used to send IPI to hart 0 -* The bit 6 is used to send IPI to hart 1 -* The bit 5 is used to send IPI to hart 2 -* The bit 4 is used to send IPI to hart 3 -*/ -u32 source_hart =current_hartid (); -u32 target_offset = (PLICSW_PENDING_PER_HART -1 ) - target_hart; -u32 per_hart_offset =PLICSW_PENDING_PER_HART * source_hart; -u32 val =1 << target_offset << per_hart_offset; - -writel (val, plicsw_dev[source_hart].plicsw_pending); -} - -void plicsw_ipi_send (u32 target_hart) -{ -if (plicsw_ipi_hart_count <= target_hart) -return ; - -/* Set PLICSW IPI */ -plic_sw_pending (target_hart); -} - -void plicsw_ipi_clear (u32 target_hart) -{ -if (plicsw_ipi_hart_count <= target_hart) -return ; - -/* Clear PLICSW IPI */ -plicsw_claim (); -plicsw_complete (); -} - -int plicsw_warm_ipi_init (void ) -{ -u32 hartid =current_hartid (); - -if (!plicsw_dev[hartid].plicsw_pending - && !plicsw_dev[hartid].plicsw_enable - && !plicsw_dev[hartid].plicsw_claim) -return -1 ; - -/* Clear PLICSW IPI */ -plicsw_ipi_clear (hartid); - -return 0 ; -} - -int plicsw_cold_ipi_init (unsigned long base,u32 hart_count) -{ -/* Setup source priority */ -uint32_t *priority = (void *)base +PLICSW_PRIORITY_BASE ; - -for (int i =0 ; i <AE350_HART_COUNT *PLICSW_PENDING_PER_HART ; i++) -writel (1 , &priority[i]); - -/* Setup target enable */ -uint32_t enable_mask =PLICSW_HART_MASK ; - -for (int i =0 ; i <AE350_HART_COUNT ; i++) { -uint32_t *enable = (void *)base +PLICSW_ENABLE_BASE - +PLICSW_ENABLE_PER_HART * i; -writel (enable_mask, &enable[0 ]); - enable_mask >>=1 ; - } - -/* Figure-out PLICSW IPI register address */ - plicsw_ipi_hart_count = hart_count; - -for (u32 hartid =0 ; hartid <AE350_HART_COUNT ; hartid++) { - plicsw_dev[hartid].source_id =0 ; - plicsw_dev[hartid].plicsw_pending = - (void *)base - +PLICSW_PENDING_BASE - + ((hartid /4 ) *4 ); - plicsw_dev[hartid].plicsw_enable = - (void *)base - +PLICSW_ENABLE_BASE - +PLICSW_ENABLE_PER_HART * hartid; - plicsw_dev[hartid].plicsw_claim = - (void *)base - +PLICSW_CONTEXT_BASE - +PLICSW_CONTEXT_CLAIM - +PLICSW_CONTEXT_PER_HART * hartid; - } - -return 0 ; -}platform/andes/ae350/plicsw.h deleted +0
-45@@ -1,44 +0,0 @@ -/* -* SPDX-License-Identifier: BSD-2-Clause -* -* Copyright (c) 2019 Andes Technology Corporation -* -* Authors: -* Zong Li <[email protected]> -* Nylon Chen <[email protected]> -*/ - -#ifndef _AE350_PLICSW_H_ -#define _AE350_PLICSW_H_ - -#define PLICSW_PRIORITY_BASE 0x4 - -#define PLICSW_PENDING_BASE 0x1000 -#define PLICSW_PENDING_PER_HART 0x8 - -#define PLICSW_ENABLE_BASE 0x2000 -#define PLICSW_ENABLE_PER_HART 0x80 - -#define PLICSW_CONTEXT_BASE 0x200000 -#define PLICSW_CONTEXT_PER_HART 0x1000 -#define PLICSW_CONTEXT_CLAIM 0x4 - -#define PLICSW_HART_MASK 0x80808080 - -struct plicsw { -u32 source_id; - -volatile uint32_t *plicsw_pending; -volatile uint32_t *plicsw_enable; -volatile uint32_t *plicsw_claim; -}; - -void plicsw_ipi_send (u32 target_hart); - -void plicsw_ipi_clear (u32 target_hart); - -int plicsw_warm_ipi_init (void ); - -int plicsw_cold_ipi_init (unsigned long base,u32 hart_count); - -#endif /* _AE350_PLICSW_H_ */ --2.34.1
Quoted 4 lines
--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
Regards,
Anup
PATCH v3 12/13 platform: andes/ae350: Add AE350 domain support
In reply to Yu Chien Peter LinAdd domains_init platform hook for Andes AE350, users can add domain description in device tree and select FDT domain support in Kconfig to achieve system-level partitioning.
---
Changes v2 -> v3
- No change since v2
--- platform/andes/ae350/platform.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
platform/andes/ae350/platform.c +11 -2
@@ -19,13 +19,14 @@#include <sbi/sbi_platform.h> #include <sbi/sbi_string.h> #include <sbi/sbi_trap.h> -#include <sbi_utils/fdt/fdt_helper.h> +#include <sbi_utils/fdt/fdt_domain.h> #include <sbi_utils/fdt/fdt_fixup.h> +#include <sbi_utils/fdt/fdt_helper.h> +#include <sbi_utils/ipi/fdt_ipi.h> #include <sbi_utils/irqchip/fdt_irqchip.h> #include <sbi_utils/reset/fdt_reset.h> #include <sbi_utils/serial/fdt_serial.h> #include <sbi_utils/timer/fdt_timer.h> -#include <sbi_utils/ipi/fdt_ipi.h> #include "platform.h" #include "cache.h"
@@ -84,6 +85,7 @@ static int ae350_final_init(bool cold_boot) fdt =fdt_get_address ();fdt_fixups (fdt); +fdt_domain_fixup (fdt);return 0 ; }
@@ -132,10 +134,17 @@ static int ae350_vendor_ext_provider(long extid, long funcid,return ret; } +static int ae350_domains_init (void ) +{ +return fdt_domains_populate (fdt_get_address ()); +} +/* Platform descriptor. */ const struct sbi_platform_operations platform_ops = { .final_init = ae350_final_init, + .domains_init = ae350_domains_init, + .console_init = fdt_serial_init, .irqchip_init = fdt_irqchip_init,
Signature · 1 line
2.34.1
PATCH v3 13/13 docs: andes-ae350.md: Update ae350 documentation for fdt driver support
In reply to Yu Chien Peter LinWe update ae350 documentation to add details about platform device tree. The nodes and their properties must be provided to properly initialize data of underlying hardware and access their mmio registers.
---
Changes v2 -> v3
- Remove "riscv,ndev" from plicsw device tree node
--- docs/platform/andes-ae350.md | 184 ++++++++++++++++++++++++++++++++++- 1 file changed, 180 insertions(+), 4 deletions(-)
docs/platform/andes-ae350.md +180 -4
@@ -18,13 +18,189 @@ The Andes AE350 platform does not have any platform-specific options. Building Andes AE350 Platform ----------------------------- -To use Linux v5.2 should be used to build Andes AE350 OpenSBI binaries by using -the compile time option FW_FDT_PATH. - -AE350's dts is included in https://github.com/andestech/linux/tree/ast-v3_2_0-release-public +AE350's dts is included in https://github.com/andestech/linux/tree/RISCV-Linux-5.4-ast-v5_1_0-branch **Linux Kernel Payload** ``` make PLATFORM=andes/ae350 FW_PAYLOAD_PATH=<linux_build_directory>/arch/riscv/boot/Image FW_FDT_PATH=<ae350.dtb path> ``` + +DTS Example: (Quad-core AX45MP) +------------------------------- + +``` + cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <60000000>; + + CPU0: cpu at 0 { + device_type = "cpu"; + reg = <0>; + status = "okay"; + compatible = "riscv"; + riscv,isa = "rv64imafdc"; + riscv,priv-major = <1>; + riscv,priv-minor = <10>; + mmu-type = "riscv,sv48"; + clock-frequency = <60000000>; + i-cache-size = <0x8000>; + i-cache-sets = <256>; + i-cache-line-size = <64>; + i-cache-block-size = <64>; + d-cache-size = <0x8000>; + d-cache-sets = <128>; + d-cache-line-size = <64>; + d-cache-block-size = <64>; + next-level-cache = <&L2>; + CPU0_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + CPU1: cpu at 1 { + device_type = "cpu"; + reg = <1>; + status = "okay"; + compatible = "riscv"; + riscv,isa = "rv64imafdc"; + riscv,priv-major = <1>; + riscv,priv-minor = <10>; + mmu-type = "riscv,sv48"; + clock-frequency = <60000000>; + i-cache-size = <0x8000>; + i-cache-sets = <256>; + i-cache-line-size = <64>; + i-cache-block-size = <64>; + d-cache-size = <0x8000>; + d-cache-sets = <128>; + d-cache-line-size = <64>; + d-cache-block-size = <64>; + next-level-cache = <&L2>; + CPU1_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + CPU2: cpu at 2 { + device_type = "cpu"; + reg = <2>; + status = "okay"; + compatible = "riscv"; + riscv,isa = "rv64imafdc"; + riscv,priv-major = <1>; + riscv,priv-minor = <10>; + mmu-type = "riscv,sv48"; + clock-frequency = <60000000>; + i-cache-size = <0x8000>; + i-cache-sets = <256>; + i-cache-line-size = <64>; + i-cache-block-size = <64>; + d-cache-size = <0x8000>; + d-cache-sets = <128>; + d-cache-line-size = <64>; + d-cache-block-size = <64>; + next-level-cache = <&L2>; + CPU2_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + CPU3: cpu at 3 { + device_type = "cpu"; + reg = <3>; + status = "okay"; + compatible = "riscv"; + riscv,isa = "rv64imafdc"; + riscv,priv-major = <1>; + riscv,priv-minor = <10>; + mmu-type = "riscv,sv48"; + clock-frequency = <60000000>; + i-cache-size = <0x8000>; + i-cache-sets = <256>; + i-cache-line-size = <64>; + i-cache-block-size = <64>; + d-cache-size = <0x8000>; + d-cache-sets = <128>; + d-cache-line-size = <64>; + d-cache-block-size = <64>; + next-level-cache = <&L2>; + CPU3_intc: interrupt-controller { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + }; + }; + }; + + soc { + #address-cells = <2>; + #size-cells = <2>; + compatible = "andestech,riscv-ae350-soc", "simple-bus"; + ranges; + + plic0: interrupt-controller at e4000000 { + compatible = "riscv,plic0"; + reg = <0x00000000 0xe4000000 0x00000000 0x02000000>; + interrupts-extended = < &CPU0_intc 11 &CPU0_intc 9 + &CPU1_intc 11 &CPU1_intc 9 + &CPU2_intc 11 &CPU2_intc 9 + &CPU3_intc 11 &CPU3_intc 9 >; + interrupt-controller; + #address-cells = <2>; + #interrupt-cells = <2>; + riscv,ndev = <71>; + }; + + plicsw: interrupt-controller at e6400000 { + compatible = "andestech,plicsw"; + reg = <0x00000000 0xe6400000 0x00000000 0x00400000>; + interrupts-extended = < &CPU0_intc 3 + &CPU1_intc 3 + &CPU2_intc 3 + &CPU3_intc 3 >; + interrupt-controller; + #address-cells = <2>; + #interrupt-cells = <2>; + }; + + plmt0: plmt0 at e6000000 { + compatible = "andestech,plmt0"; + reg = <0x00000000 0xe6000000 0x00000000 0x00100000>; + interrupts-extended = < &CPU0_intc 7 + &CPU1_intc 7 + &CPU2_intc 7 + &CPU3_intc 7 >; + }; + + wdt: wdt at f0500000 { + compatible = "andestech,atcwdt200"; + reg = <0x00000000 0xf0500000 0x00000000 0x00001000>; + interrupts = <3 4>; + interrupt-parent = <&plic0>; + clock-frequency = <15000000>; + }; + + serial0: serial at f0300000 { + compatible = "andestech,uart16550", "ns16550a"; + reg = <0x00000000 0xf0300000 0x00000000 0x00001000>; + interrupts = <9 4>; + interrupt-parent = <&plic0>; + clock-frequency = <19660800>; + current-speed = <38400>; + reg-shift = <2>; + reg-offset = <32>; + reg-io-width = <4>; + no-loopback-test = <1>; + }; + + smu: smu at f0100000 { + compatible = "andestech,atcsmu"; + reg = <0x00000000 0xf0100000 0x00000000 0x00001000>; + }; + }; +```
Signature · 1 line
2.34.1