xref: /linux/arch/riscv/errata/andes/errata.c (revision 4b660dbd9ee2059850fd30e0df420ca7a38a1856)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Erratas to be applied for Andes CPU cores
4  *
5  *  Copyright (C) 2023 Renesas Electronics Corporation.
6  *
7  * Author: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
8  */
9 
10 #include <linux/memory.h>
11 #include <linux/module.h>
12 
13 #include <asm/alternative.h>
14 #include <asm/cacheflush.h>
15 #include <asm/errata_list.h>
16 #include <asm/patch.h>
17 #include <asm/processor.h>
18 #include <asm/sbi.h>
19 #include <asm/vendorid_list.h>
20 
21 #define ANDES_AX45MP_MARCHID		0x8000000000008a45UL
22 #define ANDES_AX45MP_MIMPID		0x500UL
23 #define ANDES_SBI_EXT_ANDES		0x0900031E
24 
25 #define ANDES_SBI_EXT_IOCP_SW_WORKAROUND	1
26 
27 static long ax45mp_iocp_sw_workaround(void)
28 {
29 	struct sbiret ret;
30 
31 	/*
32 	 * ANDES_SBI_EXT_IOCP_SW_WORKAROUND SBI EXT checks if the IOCP is missing and
33 	 * cache is controllable only then CMO will be applied to the platform.
34 	 */
35 	ret = sbi_ecall(ANDES_SBI_EXT_ANDES, ANDES_SBI_EXT_IOCP_SW_WORKAROUND,
36 			0, 0, 0, 0, 0, 0);
37 
38 	return ret.error ? 0 : ret.value;
39 }
40 
41 static void errata_probe_iocp(unsigned int stage, unsigned long arch_id, unsigned long impid)
42 {
43 	static bool done;
44 
45 	if (!IS_ENABLED(CONFIG_ERRATA_ANDES_CMO))
46 		return;
47 
48 	if (done)
49 		return;
50 
51 	done = true;
52 
53 	if (arch_id != ANDES_AX45MP_MARCHID || impid != ANDES_AX45MP_MIMPID)
54 		return;
55 
56 	if (!ax45mp_iocp_sw_workaround())
57 		return;
58 
59 	/* Set this just to make core cbo code happy */
60 	riscv_cbom_block_size = 1;
61 	riscv_noncoherent_supported();
62 }
63 
64 void __init_or_module andes_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
65 					      unsigned long archid, unsigned long impid,
66 					      unsigned int stage)
67 {
68 	if (stage == RISCV_ALTERNATIVES_BOOT)
69 		errata_probe_iocp(stage, archid, impid);
70 
71 	/* we have nothing to patch here ATM so just return back */
72 }
73