Re: [PATCH v5 3/6] riscv: errata: Add Andes alternative ports

Conor Dooley
2022-12-17T21:20:13Z

[-- Attachment #1.1: Type: text/plain, Size: 8204 bytes --]

On Mon, Dec 12, 2022 at 11:55:02AM +0000, Prabhakar wrote:
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
>
> Add required ports of the Alternative scheme for Andes CPU cores.
>
> I/O Coherence Port (IOCP) provides an AXI interface for connecting external
> non-caching masters, such as DMA controllers. IOCP is a specification
> option and is disabled on the Renesas RZ/Five SoC due to this reason cache
> management needs a software workaround.
>
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> ---
> v4 -> v5
> * Sorted the Kconfig/Makefile/Switch based on Core name
> * Added a comments
> * Introduced RZFIVE_SBI_EXT_IOCP_SW_WORKAROUND SBI EXT ID to check if
> CMO needs to be applied. Is there a way we can access the DTB while patching
> as we can drop this SBI EXT ID and add a DT property instead for cmo?
>
> RFC v3 -> v4
> * New patch
> ---
> arch/riscv/Kconfig.erratas | 22 +++++++
> arch/riscv/errata/Makefile | 1 +
> arch/riscv/errata/andes/Makefile | 1 +
> arch/riscv/errata/andes/errata.c | 93 ++++++++++++++++++++++++++++
> arch/riscv/include/asm/alternative.h | 3 +
> arch/riscv/include/asm/errata_list.h | 5 ++
> arch/riscv/kernel/alternative.c | 5 ++
> 7 files changed, 130 insertions(+)
> create mode 100644 arch/riscv/errata/andes/Makefile
> create mode 100644 arch/riscv/errata/andes/errata.c
>
> diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
> index 69621ae6d647..f0f0c1abd52b 100644
> --- a/arch/riscv/Kconfig.erratas
> +++ b/arch/riscv/Kconfig.erratas
> @@ -1,5 +1,27 @@
> menu "CPU errata selection"
>
> +config ERRATA_ANDES
> + bool "Andes AX45MP errata"
> + depends on !XIP_KERNEL
> + select RISCV_ALTERNATIVE
> + help
> + All Andes errata Kconfig depend on this Kconfig. Disabling
> + this Kconfig will disable all Andes errata. Please say "Y"
> + here if your platform uses Andes CPU cores.
> +
> + Otherwise, please say "N" here to avoid unnecessary overhead.
> +
> +config ERRATA_ANDES_CMO
> + bool "Apply Andes cache management errata"
> + depends on ERRATA_ANDES && MMU && ARCH_R9A07G043
> + select RISCV_DMA_NONCOHERENT
> + default y
> + help
> + This will apply the cache management errata to handle the
> + non-standard handling on non-coherent operations on Andes cores.
> +
> + If you don't know what to do here, say "Y".
> +
> config ERRATA_SIFIVE
> bool "SiFive errata"
> depends on !XIP_KERNEL
> diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
> index a1055965fbee..6f1c693af92d 100644
> --- a/arch/riscv/errata/Makefile
> +++ b/arch/riscv/errata/Makefile
> @@ -1,2 +1,3 @@
> +obj-$(CONFIG_ERRATA_ANDES) += andes/
> obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
> obj-$(CONFIG_ERRATA_THEAD) += thead/
> diff --git a/arch/riscv/errata/andes/Makefile b/arch/riscv/errata/andes/Makefile
> new file mode 100644
> index 000000000000..2d644e19caef
> --- /dev/null
> +++ b/arch/riscv/errata/andes/Makefile
> @@ -0,0 +1 @@
> +obj-y += errata.o
> diff --git a/arch/riscv/errata/andes/errata.c b/arch/riscv/errata/andes/errata.c
> new file mode 100644
> index 000000000000..3d04f15df8d5
> --- /dev/null
> +++ b/arch/riscv/errata/andes/errata.c
> @@ -0,0 +1,93 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Erratas to be applied for Andes CPU cores
> + *
> + * Copyright (C) 2022 Renesas Electronics Corporation.
> + *
> + * Author: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +
> +#include <asm/alternative.h>
> +#include <asm/cacheflush.h>
> +#include <asm/errata_list.h>
> +#include <asm/patch.h>
> +#include <asm/sbi.h>
> +#include <asm/vendorid_list.h>
> +
> +#define ANDESTECH_AX45MP_MARCHID 0x8000000000008a45UL
> +#define ANDESTECH_AX45MP_MIMPID 0x500UL
> +#define ANDESTECH_SBI_EXT_ANDES 0x0900031E
> +
> +#define RZFIVE_SBI_EXT_IOCP_SW_WORKAROUND 0
> +
> +static long ax45mp_iocp_sw_workaround(void)
> +{
> + struct sbiret ret;
> +
> + ret = sbi_ecall(ANDESTECH_SBI_EXT_ANDES, RZFIVE_SBI_EXT_IOCP_SW_WORKAROUND,
> + 0, 0, 0, 0, 0, 0);

Seeing as you need a new version for some of the other bits, I think it
would be good to add a minor comment here somewhere (be it here or the
commit message) that links to the SBI specs for this.
I think this looks pretty good though.
Thanks,
Conor.

> +
> + return ret.error ? 0 : ret.value;
> +}
> +
> +static bool errata_probe_iocp(unsigned int stage, unsigned long arch_id, unsigned long impid)
> +{
> + if (!IS_ENABLED(CONFIG_ERRATA_ANDES_CMO))
> + return false;
> +
> + if (arch_id != ANDESTECH_AX45MP_MARCHID || impid != ANDESTECH_AX45MP_MIMPID)
> + return false;
> +
> + if (!ax45mp_iocp_sw_workaround())
> + return false;
> +
> + /* Set this just to make core cbo code happy */
> + riscv_cbom_block_size = 1;
> + riscv_noncoherent_supported();
> +
> + return true;
> +}
> +
> +static u32 andes_errata_probe(unsigned int stage, unsigned long archid, unsigned long impid)
> +{
> + u32 cpu_req_errata = 0;
> +
> + /*
> + * In the absence of the I/O Coherency Port, access to certain peripherals
> + * requires vendor specific DMA handling.
> + */
> + if (errata_probe_iocp(stage, archid, impid))
> + cpu_req_errata |= BIT(ERRATA_ANDESTECH_NO_IOCP);
> +
> + return cpu_req_errata;
> +}
> +
> +void __init_or_module andes_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> + unsigned long archid, unsigned long impid,
> + unsigned int stage)
> +{
> + u32 cpu_req_errata = andes_errata_probe(stage, archid, impid);
> + struct alt_entry *alt;
> + u32 tmp;
> +
> + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
> + return;
> +
> + for (alt = begin; alt < end; alt++) {
> + if (alt->vendor_id != ANDESTECH_VENDOR_ID)
> + continue;
> + if (alt->errata_id >= ERRATA_ANDESTECH_NUMBER)
> + continue;
> +
> + tmp = BIT(alt->errata_id);
> + if (cpu_req_errata & tmp) {
> + patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
> +
> + riscv_alternative_fix_offsets(alt->old_ptr, alt->alt_len,
> + alt->old_ptr - alt->alt_ptr);
> + }
> + }
> +}
> diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
> index 1bd4027d34ca..e3a8e603eb5a 100644
> --- a/arch/riscv/include/asm/alternative.h
> +++ b/arch/riscv/include/asm/alternative.h
> @@ -43,6 +43,9 @@ struct errata_checkfunc_id {
> bool (*func)(struct alt_entry *alt);
> };
>
> +void andes_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> + unsigned long archid, unsigned long impid,
> + unsigned int stage);
> void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> unsigned long archid, unsigned long impid,
> unsigned int stage);
> diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
> index 4180312d2a70..2ba7e6e74540 100644
> --- a/arch/riscv/include/asm/errata_list.h
> +++ b/arch/riscv/include/asm/errata_list.h
> @@ -9,6 +9,11 @@
> #include <asm/csr.h>
> #include <asm/vendorid_list.h>
>
> +#ifdef CONFIG_ERRATA_ANDES
> +#define ERRATA_ANDESTECH_NO_IOCP 0
> +#define ERRATA_ANDESTECH_NUMBER 1
> +#endif
> +
> #ifdef CONFIG_ERRATA_SIFIVE
> #define ERRATA_SIFIVE_CIP_453 0
> #define ERRATA_SIFIVE_CIP_1200 1
> diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
> index e12b06940154..0a09cbbc2593 100644
> --- a/arch/riscv/kernel/alternative.c
> +++ b/arch/riscv/kernel/alternative.c
> @@ -40,6 +40,11 @@ static void __init_or_module riscv_fill_cpu_mfr_info(struct cpu_manufacturer_inf
> #endif
>
> switch (cpu_mfr_info->vendor_id) {
> +#ifdef CONFIG_ERRATA_ANDES
> + case ANDESTECH_VENDOR_ID:
> + cpu_mfr_info->patch_func = andes_errata_patch_func;
> + break;
> +#endif
> #ifdef CONFIG_ERRATA_SIFIVE
> case SIFIVE_VENDOR_ID:
> cpu_mfr_info->patch_func = sifive_errata_patch_func;
> --
> 2.25.1
>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]