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 #include <asm/vendor_extensions.h>
21
22 #define ANDES_AX45MP_MARCHID 0x8000000000008a45UL
23 #define ANDES_AX45MP_MIMPID 0x500UL
24 #define ANDES_SBI_EXT_ANDES 0x0900031E
25
26 #define ANDES_SBI_EXT_IOCP_SW_WORKAROUND 1
27
ax45mp_iocp_sw_workaround(void)28 static long ax45mp_iocp_sw_workaround(void)
29 {
30 struct sbiret ret;
31
32 /*
33 * ANDES_SBI_EXT_IOCP_SW_WORKAROUND SBI EXT checks if the IOCP is missing and
34 * cache is controllable only then CMO will be applied to the platform.
35 */
36 ret = sbi_ecall(ANDES_SBI_EXT_ANDES, ANDES_SBI_EXT_IOCP_SW_WORKAROUND,
37 0, 0, 0, 0, 0, 0);
38
39 return ret.error ? 0 : ret.value;
40 }
41
errata_probe_iocp(unsigned int stage,unsigned long arch_id,unsigned long impid)42 static void errata_probe_iocp(unsigned int stage, unsigned long arch_id, unsigned long impid)
43 {
44 static bool done;
45
46 if (!IS_ENABLED(CONFIG_ERRATA_ANDES_CMO))
47 return;
48
49 if (done)
50 return;
51
52 done = true;
53
54 if (arch_id != ANDES_AX45MP_MARCHID || impid != ANDES_AX45MP_MIMPID)
55 return;
56
57 if (!ax45mp_iocp_sw_workaround())
58 return;
59
60 /* Set this just to make core cbo code happy */
61 riscv_cbom_block_size = 1;
62 riscv_noncoherent_supported();
63 }
64
andes_errata_patch_func(struct alt_entry * begin,struct alt_entry * end,unsigned long archid,unsigned long impid,unsigned int stage)65 void __init_or_module andes_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
66 unsigned long archid, unsigned long impid,
67 unsigned int stage)
68 {
69 BUILD_BUG_ON(ERRATA_ANDES_NUMBER >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
70
71 if (stage == RISCV_ALTERNATIVES_BOOT)
72 errata_probe_iocp(stage, archid, impid);
73
74 /* we have nothing to patch here ATM so just return back */
75 }
76