Skip to content

Commit

Permalink
riscv: errata: Add Andes alternative ports
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Conor Dooley <[email protected]>
Tested-by: Conor Dooley <[email protected]> # tyre-kicking on a d1
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Palmer Dabbelt <[email protected]>
  • Loading branch information
prabhakarlad authored and palmer-dabbelt committed Sep 1, 2023
1 parent d6ca3a5 commit e021ae7
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 0 deletions.
21 changes: 21 additions & 0 deletions arch/riscv/Kconfig.errata
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
menu "CPU errata selection"

config ERRATA_ANDES
bool "Andes AX45MP errata"
depends on 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 RISCV_ALTERNATIVE
Expand Down
1 change: 1 addition & 0 deletions arch/riscv/errata/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ ifdef CONFIG_RELOCATABLE
KBUILD_CFLAGS += -fno-pie
endif

obj-$(CONFIG_ERRATA_ANDES) += andes/
obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
obj-$(CONFIG_ERRATA_THEAD) += thead/
1 change: 1 addition & 0 deletions arch/riscv/errata/andes/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
obj-y += errata.o
66 changes: 66 additions & 0 deletions arch/riscv/errata/andes/errata.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Erratas to be applied for Andes CPU cores
*
* Copyright (C) 2023 Renesas Electronics Corporation.
*
* Author: Lad Prabhakar <[email protected]>
*/

#include <linux/memory.h>
#include <linux/module.h>

#include <asm/alternative.h>
#include <asm/cacheflush.h>
#include <asm/errata_list.h>
#include <asm/patch.h>
#include <asm/processor.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 ANDES_SBI_EXT_IOCP_SW_WORKAROUND 1

static long ax45mp_iocp_sw_workaround(void)
{
struct sbiret ret;

/*
* ANDES_SBI_EXT_IOCP_SW_WORKAROUND SBI EXT checks if the IOCP is missing and
* cache is controllable only then CMO will be applied to the platform.
*/
ret = sbi_ecall(ANDESTECH_SBI_EXT_ANDES, ANDES_SBI_EXT_IOCP_SW_WORKAROUND,
0, 0, 0, 0, 0, 0);

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;
}

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)
{
errata_probe_iocp(stage, archid, impid);

/* we have nothing to patch here ATM so just return back */
}
3 changes: 3 additions & 0 deletions arch/riscv/include/asm/alternative.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ struct alt_entry {
u32 patch_id; /* The patch ID (erratum ID or cpufeature ID) */
};

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);
Expand Down
5 changes: 5 additions & 0 deletions arch/riscv/include/asm/errata_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
#include <asm/hwcap.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
Expand Down
5 changes: 5 additions & 0 deletions arch/riscv/kernel/alternative.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ static void riscv_fill_cpu_mfr_info(struct cpu_manufacturer_info_t *cpu_mfr_info

cpu_mfr_info->feature_probe_func = NULL;
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;
Expand Down

0 comments on commit e021ae7

Please sign in to comment.