Unverified Commit e021ae7f authored by Lad Prabhakar's avatar Lad Prabhakar Committed by Palmer Dabbelt
Browse files

riscv: errata: Add Andes alternative ports



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: default avatarLad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: default avatarConor Dooley <conor.dooley@microchip.com>
Tested-by: Conor Dooley <conor.dooley@microchip.com> # tyre-kicking on a d1
Link: https://lore.kernel.org/r/20230818135723.80612-3-prabhakar.mahadev-lad.rj@bp.renesas.com


Signed-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent d6ca3a56
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
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
+1 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
obj-y += errata.o
+66 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Erratas to be applied for Andes CPU cores
 *
 *  Copyright (C) 2023 Renesas Electronics Corporation.
 *
 * Author: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
 */

#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 −0
Original line number Diff line number Diff line
@@ -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);
Loading