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