Unverified Commit d20ec752 authored by Heiko Stuebner's avatar Heiko Stuebner Committed by Palmer Dabbelt
Browse files

riscv: implement cache-management errata for T-Head SoCs



The T-Head C906 and C910 implement a scheme for handling
cache operations different from the generic Zicbom extension.

Add an errata for it next to the generic dma coherency ops.

Reviewed-by: default avatarSamuel Holland <samuel@sholland.org>
Tested-by: default avatarSamuel Holland <samuel@sholland.org>
Reviewed-by: default avatarGuo Ren <guoren@kernel.org>
Signed-off-by: default avatarHeiko Stuebner <heiko@sntech.de>
Link: https://lore.kernel.org/r/20220706231536.2041855-5-heiko@sntech.de


Signed-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent 1631ba12
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -55,4 +55,15 @@ config ERRATA_THEAD_PBMT


	  If you don't know what to do here, say "Y".
	  If you don't know what to do here, say "Y".


config ERRATA_THEAD_CMO
	bool "Apply T-Head cache management errata"
	depends on ERRATA_THEAD
	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 T-Head SoCs.

	  If you don't know what to do here, say "Y".

endmenu
endmenu
+20 −0
Original line number Original line Diff line number Diff line
@@ -27,6 +27,23 @@ static bool errata_probe_pbmt(unsigned int stage,
	return false;
	return false;
}
}


static bool errata_probe_cmo(unsigned int stage,
			     unsigned long arch_id, unsigned long impid)
{
#ifdef CONFIG_ERRATA_THEAD_CMO
	if (arch_id != 0 || impid != 0)
		return false;

	if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
		return false;

	riscv_noncoherent_supported();
	return true;
#else
	return false;
#endif
}

static u32 thead_errata_probe(unsigned int stage,
static u32 thead_errata_probe(unsigned int stage,
			      unsigned long archid, unsigned long impid)
			      unsigned long archid, unsigned long impid)
{
{
@@ -35,6 +52,9 @@ static u32 thead_errata_probe(unsigned int stage,
	if (errata_probe_pbmt(stage, archid, impid))
	if (errata_probe_pbmt(stage, archid, impid))
		cpu_req_errata |= (1U << ERRATA_THEAD_PBMT);
		cpu_req_errata |= (1U << ERRATA_THEAD_PBMT);


	if (errata_probe_cmo(stage, archid, impid))
		cpu_req_errata |= (1U << ERRATA_THEAD_CMO);

	return cpu_req_errata;
	return cpu_req_errata;
}
}


+43 −5
Original line number Original line Diff line number Diff line
@@ -16,7 +16,8 @@


#ifdef CONFIG_ERRATA_THEAD
#ifdef CONFIG_ERRATA_THEAD
#define	ERRATA_THEAD_PBMT 0
#define	ERRATA_THEAD_PBMT 0
#define	ERRATA_THEAD_NUMBER 1
#define	ERRATA_THEAD_CMO 1
#define	ERRATA_THEAD_NUMBER 2
#endif
#endif


#define	CPUFEATURE_SVPBMT 0
#define	CPUFEATURE_SVPBMT 0
@@ -94,17 +95,54 @@ asm volatile(ALTERNATIVE( \
#define ALT_THEAD_PMA(_val)
#define ALT_THEAD_PMA(_val)
#endif
#endif


/*
 * dcache.ipa rs1 (invalidate, physical address)
 * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
 *   0000001    01010      rs1       000      00000  0001011
 * dache.iva rs1 (invalida, virtual address)
 *   0000001    00110      rs1       000      00000  0001011
 *
 * dcache.cpa rs1 (clean, physical address)
 * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
 *   0000001    01001      rs1       000      00000  0001011
 * dcache.cva rs1 (clean, virtual address)
 *   0000001    00100      rs1       000      00000  0001011
 *
 * dcache.cipa rs1 (clean then invalidate, physical address)
 * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
 *   0000001    01011      rs1       000      00000  0001011
 * dcache.civa rs1 (... virtual address)
 *   0000001    00111      rs1       000      00000  0001011
 *
 * sync.s (make sure all cache operations finished)
 * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
 *   0000000    11001     00000      000      00000  0001011
 */
#define THEAD_inval_A0	".long 0x0265000b"
#define THEAD_clean_A0	".long 0x0245000b"
#define THEAD_flush_A0	".long 0x0275000b"
#define THEAD_SYNC_S	".long 0x0190000b"

#define ALT_CMO_OP(_op, _start, _size, _cachesize)			\
#define ALT_CMO_OP(_op, _start, _size, _cachesize)			\
asm volatile(ALTERNATIVE(						\
asm volatile(ALTERNATIVE_2(						\
	__nops(5),							\
	__nops(6),							\
	"mv a0, %1\n\t"							\
	"mv a0, %1\n\t"							\
	"j 2f\n\t"							\
	"j 2f\n\t"							\
	"3:\n\t"							\
	"3:\n\t"							\
	"cbo." __stringify(_op) " (a0)\n\t"				\
	"cbo." __stringify(_op) " (a0)\n\t"				\
	"add a0, a0, %0\n\t"						\
	"add a0, a0, %0\n\t"						\
	"2:\n\t"							\
	"2:\n\t"							\
	"bltu a0, %2, 3b\n\t", 0,					\
	"bltu a0, %2, 3b\n\t"						\
		CPUFEATURE_ZICBOM, CONFIG_RISCV_ISA_ZICBOM)		\
	"nop", 0, CPUFEATURE_ZICBOM, CONFIG_RISCV_ISA_ZICBOM,		\
	"mv a0, %1\n\t"							\
	"j 2f\n\t"							\
	"3:\n\t"							\
	THEAD_##_op##_A0 "\n\t"						\
	"add a0, a0, %0\n\t"						\
	"2:\n\t"							\
	"bltu a0, %2, 3b\n\t"						\
	THEAD_SYNC_S, THEAD_VENDOR_ID,					\
			ERRATA_THEAD_CMO, CONFIG_ERRATA_THEAD_CMO)	\
	: : "r"(_cachesize),						\
	: : "r"(_cachesize),						\
	    "r"((unsigned long)(_start) & ~((_cachesize) - 1UL)),	\
	    "r"((unsigned long)(_start) & ~((_cachesize) - 1UL)),	\
	    "r"((unsigned long)(_start) + (_size))			\
	    "r"((unsigned long)(_start) + (_size))			\