sfp.c 3.51 KB
Newer Older
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
 * Copyright 2021 NXP
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <caam.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <sfp.h>
#include <sfp_error_codes.h>

static uintptr_t g_nxp_sfp_addr;
static uint32_t srk_hash[SRK_HASH_SIZE/sizeof(uint32_t)]
					__aligned(CACHE_WRITEBACK_GRANULE);

void sfp_init(uintptr_t nxp_sfp_addr)
{
	g_nxp_sfp_addr = nxp_sfp_addr;
}

uintptr_t get_sfp_addr(void)
{
	return g_nxp_sfp_addr;
}

uint32_t *get_sfp_srk_hash(void)
{
	struct sfp_ccsr_regs_t *sfp_ccsr_regs =
			(void *) (g_nxp_sfp_addr + SFP_FUSE_REGS_OFFSET);
	int i = 0;

	/* Add comparison of hash with SFP hash here */
	for (i = 0; i < SRK_HASH_SIZE/sizeof(uint32_t); i++)
		srk_hash[i] =
			mmio_read_32((uintptr_t)&sfp_ccsr_regs->srk_hash[i]);

	return srk_hash;
}

void set_sfp_wr_disable(void)
{
	/*
	 * Mark SFP Write Disable and Write Disable Lock
	 * Bit to prevent write to SFP fuses like
	 * OUID's, Key Revocation fuse etc
	 */
	void *sfpcr = (void *)(g_nxp_sfp_addr + SFP_SFPCR_OFFSET);
	uint32_t sfpcr_val;

	sfpcr_val = sfp_read32(sfpcr);
	sfpcr_val |= (SFP_SFPCR_WD | SFP_SFPCR_WDL);
	sfp_write32(sfpcr, sfpcr_val);
}

int sfp_program_fuses(void)
{
	uint32_t ingr;
	uint32_t sfp_cmd_status = 0U;
	int ret = 0;

	/* Program SFP fuses from mirror registers */
	sfp_write32((void *)(g_nxp_sfp_addr + SFP_INGR_OFFSET),
		    SFP_INGR_PROGFB_CMD);

	/* Wait until fuse programming is successful */
	do {
		ingr = sfp_read32(g_nxp_sfp_addr + SFP_INGR_OFFSET);
	} while (ingr & SFP_INGR_PROGFB_CMD);

	/* Check for SFP fuse programming error */
	sfp_cmd_status = sfp_read32(g_nxp_sfp_addr + SFP_INGR_OFFSET)
			 & SFP_INGR_ERROR_MASK;

	if (sfp_cmd_status != 0U) {
		return ERROR_PROGFB_CMD;
	}

	return ret;
}

uint32_t sfp_read_oem_uid(uint8_t oem_uid)
{
	uint32_t val = 0U;
	struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr
							+ SFP_FUSE_REGS_OFFSET);

	if (oem_uid > MAX_OEM_UID) {
		ERROR("Invalid OEM UID received.\n");
		return ERROR_OEMUID_WRITE;
	}

	val = sfp_read32(&sfp_ccsr_regs->oem_uid[oem_uid]);

	return val;
}

/*
 * return val:  0 - No update required.
 *              1 - successful update done.
 *              ERROR_OEMUID_WRITE - Invalid OEM UID
 */
uint32_t sfp_write_oem_uid(uint8_t oem_uid, uint32_t sfp_val)
{
	uint32_t val = 0U;
	struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr
							+ SFP_FUSE_REGS_OFFSET);

	val = sfp_read_oem_uid(oem_uid);

	if (val == ERROR_OEMUID_WRITE) {
		return ERROR_OEMUID_WRITE;
	}

	/* Counter already set. No need to do anything */
	if ((val & sfp_val) != 0U) {
		return 0U;
	}

	val |= sfp_val;

	INFO("SFP Value is %x for setting sfp_val = %d\n", val, sfp_val);

	sfp_write32(&sfp_ccsr_regs->oem_uid[oem_uid], val);

	return 1U;
}

int sfp_check_its(void)
{
	struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr
							+ SFP_FUSE_REGS_OFFSET);

	if ((sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_ITS_MASK) != 0) {
		return 1;
	} else {
		return 0;
	}
}

int sfp_check_oem_wp(void)
{
	struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr
							+ SFP_FUSE_REGS_OFFSET);

	if ((sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_WP_MASK) != 0) {
		return 1;
	} else {
		return 0;
	}
}

/* This function returns ospr's key_revoc values.*/
uint32_t get_key_revoc(void)
{
	struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr
							+ SFP_FUSE_REGS_OFFSET);

	return (sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_KEY_REVOC_MASK) >>
						OSPR_KEY_REVOC_SHIFT;
}