1/*
2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#include <autoconf.h>
8#include <elfloader.h>
9#include <printf.h>
10
11/* The code for enabling SError is from L4T (Linux for Tegra).
12 * Read the Parker TRM 17.12 and 17.13 for NVIDIA-specific
13 * SError extensions and the ARI (abstract request interface).
14 */
15
16
17#define SMC_SIP_INVOKE_MCE      0xc2ffff00
18#define MCE_SMC_ENUM_MAX        0xff
19#define ARI_MCA_GLOBAL_CONFIG   0x12
20#define ARI_MCA_WRITE_SERR      0x2
21#define NR_SMC_REGS             6
22
23typedef union {
24    struct {
25        uint8_t cmd;
26        uint8_t subidx;
27        uint8_t idx;
28        uint8_t inst;
29    };
30    struct {
31        uint32_t low;
32        uint32_t high;
33    };
34    uint64_t data;
35} mca_cmd_t;
36
37struct mce_regs {
38    uint64_t args[NR_SMC_REGS];
39};
40
41static __attribute__((noinline)) int send_smc(uint8_t func, struct mce_regs *regs)
42{
43    uint32_t ret = SMC_SIP_INVOKE_MCE | (func & MCE_SMC_ENUM_MAX);
44    asm volatile(
45        "mov    x0, %x0\n"
46        "ldp    x1, x2, [%1, #16 * 0] \n"
47        "ldp    x3, x4, [%1, #16 * 1] \n"
48        "ldp    x5, x6, [%1, #16 * 2] \n"
49        "isb\n"
50        "smc #0\n"
51        "mov %x0, x0\n"
52        "stp x0, x1, [%1, #16 * 0]\n"
53        "stp x2, x3, [%1, #16 * 1]\n"
54        : "+r"(ret)
55        : "r"(regs)
56        : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8",
57        "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17");
58    return ret;
59}
60
61
62static void tegra_mce_write_uncore_mca(mca_cmd_t cmd, uint64_t data, uint32_t *err)
63{
64    struct mce_regs regs;
65    regs.args[0] = cmd.data;
66    regs.args[1] = data;
67    send_smc(13, &regs);
68    *err = (uint32_t)regs.args[3];
69}
70
71static void enable_serr(void)
72{
73    uint32_t err;
74    mca_cmd_t cmd;
75    cmd.data = 0;
76    cmd.cmd = ARI_MCA_WRITE_SERR;
77    cmd.idx = ARI_MCA_GLOBAL_CONFIG;
78    tegra_mce_write_uncore_mca(cmd, 1, &err);
79    printf("Enabling TX2 SError result %d\n", err);
80}
81
82/* Enable SError report for TX2 */
83void platform_init(void)
84{
85    enable_serr();
86}
87
88