summaryrefslogtreecommitdiffstats
path: root/bsps/arm/imxrt/mcux-sdk/drivers/xecc/fsl_xecc.c
blob: fa6b7984c74bcaf9129142f2bab1aac0119d1c12 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * Copyright 2019-2020 NXP
 * All rights reserved.
 *
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "fsl_xecc.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/

/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.xecc"
#endif

/*******************************************************************************
 * Prototypes
 ******************************************************************************/
/*******************************************************************************
 * Variables
 ******************************************************************************/
/*******************************************************************************
 * Code
 ******************************************************************************/
/*!
 * brief XECC module initialization function.
 *
 * param base XECC base address.
 */
void XECC_Init(XECC_Type *base, const xecc_config_t *config)
{
    /* Enable all the interrupt status */
    base->ERR_STAT_EN = kXECC_AllInterruptsStatusEnable;
    /* Clear all the interrupt status */
    base->ERR_STATUS = kXECC_AllInterruptsFlag;
    /* Disable all the interrpt */
    base->ERR_SIG_EN = 0U;

    /* Set ECC regions, which are 4KB aligned */
    base->ECC_BASE_ADDR0 = config->Region0BaseAddress >> 12U;
    base->ECC_END_ADDR0  = config->Region0EndAddress >> 12U;
    base->ECC_BASE_ADDR1 = config->Region1BaseAddress >> 12U;
    base->ECC_END_ADDR1  = config->Region1EndAddress >> 12U;
    base->ECC_BASE_ADDR2 = config->Region2BaseAddress >> 12U;
    base->ECC_END_ADDR2  = config->Region2EndAddress >> 12U;
    base->ECC_BASE_ADDR3 = config->Region3BaseAddress >> 12U;
    base->ECC_END_ADDR3  = config->Region3EndAddress >> 12U;

    /* Enable ECC function */
    base->ECC_CTRL = XECC_ECC_CTRL_ECC_EN(config->enableXECC);
    base->ECC_CTRL |= XECC_ECC_CTRL_WECC_EN(config->enableWriteECC);
    base->ECC_CTRL |= XECC_ECC_CTRL_RECC_EN(config->enableReadECC);
    base->ECC_CTRL |= XECC_ECC_CTRL_SWAP_EN(config->enableSwap);

    /* Make sure XECC register configuration operation has been done. */
    __DSB();
}

/*!
 * brief Deinitializes the XECC.
 *
 */
void XECC_Deinit(XECC_Type *base)
{
    /* Disable ECC function */
    base->ECC_CTRL &= ~XECC_ECC_CTRL_ECC_EN(1);
}

void XECC_GetDefaultConfig(xecc_config_t *config)
{
    assert(NULL != config);

    /* Initializes the configure structure to zero. */
    (void)memset(config, 0, sizeof(*config));

    /* Default XECC function */
    config->enableXECC = false;
    /* Default write ECC function */
    config->enableWriteECC = false;
    /* Default read ECC function */
    config->enableReadECC = false;
    /* Default swap function */
    config->enableSwap = false;

    /* ECC region 0 base address */
    config->Region0BaseAddress = 0U;
    /* ECC region 0 end address */
    config->Region0EndAddress = 0U;
    /* ECC region 1 base address */
    config->Region1BaseAddress = 0U;
    /* ECC region 1 end address */
    config->Region1EndAddress = 0U;
    /* ECC region 2 base address */
    config->Region2BaseAddress = 0U;
    /* ECC region 2 end address */
    config->Region2EndAddress = 0U;
    /* ECC region 3 base address */
    config->Region3BaseAddress = 0U;
    /* ECC region 3 end address */
    config->Region3EndAddress = 0U;
}

/* Mainly use for debug, it can be deprecated when release */
status_t XECC_ErrorInjection(XECC_Type *base, uint32_t errordata, uint8_t erroreccdata)
{
    status_t status = kStatus_Success;

    if ((errordata != 0x00U) || (erroreccdata != 0x00U))
    {
        /* error data injection */
        base->ERR_DATA_INJ = errordata;
        /* error ecc code injection */
        base->ERR_ECC_INJ = erroreccdata;
        /* Make sure injection operation has been done. */
        __DSB();
    }
    else
    {
        status = kStatus_Fail;
    }

    return status;
}

void XECC_GetSingleErrorInfo(XECC_Type *base, xecc_single_error_info_t *info)
{
    assert(info != NULL);

    info->singleErrorAddress  = base->SINGLE_ERR_ADDR;
    info->singleErrorData     = base->SINGLE_ERR_DATA;
    info->singleErrorEccCode  = base->SINGLE_ERR_ECC;
    info->singleErrorBitField = base->SINGLE_ERR_BIT_FIELD;
    info->singleErrorBitPos   = base->SINGLE_ERR_POS;
}

void XECC_GetMultiErrorInfo(XECC_Type *base, xecc_multi_error_info_t *info)
{
    assert(info != NULL);

    info->multiErrorAddress  = base->MULTI_ERR_ADDR;
    info->multiErrorData     = base->MULTI_ERR_DATA;
    info->multiErrorEccCode  = base->MULTI_ERR_ECC;
    info->multiErrorBitField = base->MULTI_ERR_BIT_FIELD;
}