pld: validate exported functions by including its own .h
[openocd.git] / src / pld / certus.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2022 by Daniel Anselmi *
5 * danselmi@gmx.ch *
6 ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include "certus.h"
13 #include "lattice.h"
14 #include "lattice_cmd.h"
15
16 #define LSC_ENABLE_X 0x74
17 #define LSC_REFRESH 0x79
18 #define LSC_DEVICE_CTRL 0x7D
19
20 int lattice_certus_read_status(struct jtag_tap *tap, uint64_t *status, uint64_t out)
21 {
22 return lattice_read_u64_register(tap, LSC_READ_STATUS, status, out);
23 }
24
25 int lattice_certus_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint32_t out)
26 {
27 return lattice_read_u32_register(tap, READ_USERCODE, usercode, out, false);
28 }
29
30 int lattice_certus_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode)
31 {
32 LOG_ERROR("Not supported to write usercode on certus devices");
33 return ERROR_FAIL;
34 }
35
36 static int lattice_certus_enable_transparent_mode(struct jtag_tap *tap)
37 {
38 struct scan_field field;
39
40 int retval = lattice_set_instr(tap, LSC_ENABLE_X, TAP_IDLE);
41 if (retval != ERROR_OK)
42 return retval;
43
44 uint8_t buffer = 0x0;
45 field.num_bits = 8;
46 field.out_value = &buffer;
47 field.in_value = NULL;
48 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
49 jtag_add_runtest(2, TAP_IDLE);
50
51 return jtag_execute_queue();
52 }
53
54 static int lattice_certus_erase_device(struct lattice_pld_device *lattice_device)
55 {
56 struct jtag_tap *tap = lattice_device->tap;
57 if (!tap)
58 return ERROR_FAIL;
59
60 int retval = lattice_set_instr(tap, LSC_DEVICE_CTRL, TAP_IRPAUSE);
61 if (retval != ERROR_OK)
62 return retval;
63
64 struct scan_field field;
65 uint8_t buffer = 8;
66 field.num_bits = 8;
67 field.out_value = &buffer;
68 field.in_value = NULL;
69 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
70 jtag_add_runtest(2, TAP_IDLE);
71 retval = jtag_execute_queue();
72 if (retval != ERROR_OK)
73 return retval;
74
75 retval = lattice_set_instr(tap, LSC_DEVICE_CTRL, TAP_IDLE);
76 if (retval != ERROR_OK)
77 return retval;
78 buffer = 0;
79 field.num_bits = 8;
80 field.out_value = &buffer;
81 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
82 jtag_add_runtest(2, TAP_IDLE);
83 retval = jtag_execute_queue();
84 if (retval != ERROR_OK)
85 return retval;
86
87 retval = lattice_set_instr(tap, ISC_ERASE, TAP_IDLE);
88 if (retval != ERROR_OK)
89 return retval;
90 buffer = 0;
91 field.num_bits = 8;
92 field.out_value = &buffer;
93 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
94 jtag_add_runtest(100, TAP_IDLE);
95 jtag_add_sleep(5000);
96 retval = jtag_execute_queue();
97 if (retval != ERROR_OK)
98 return retval;
99
100 /* check done is cleared and fail is cleared */
101 const uint64_t status_done_flag = 0x100;
102 const uint64_t status_fail_flag = 0x2000;
103 return lattice_verify_status_register_u64(lattice_device, 0x0, 0x0, status_done_flag | status_fail_flag);
104 }
105
106 static int lattice_certus_enable_programming(struct jtag_tap *tap)
107 {
108 struct scan_field field;
109
110 int retval = lattice_set_instr(tap, LSC_REFRESH, TAP_IDLE);
111 if (retval != ERROR_OK)
112 return retval;
113 jtag_add_runtest(2, TAP_IDLE);
114 retval = jtag_execute_queue();
115 if (retval != ERROR_OK)
116 return retval;
117
118 retval = lattice_set_instr(tap, ISC_ENABLE, TAP_IDLE);
119 if (retval != ERROR_OK)
120 return retval;
121 uint8_t buffer = 0;
122 field.num_bits = 8;
123 field.out_value = &buffer;
124 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
125 jtag_add_runtest(2, TAP_IDLE);
126 return jtag_execute_queue();
127 }
128
129 static int lattice_certus_init_address(struct jtag_tap *tap)
130 {
131 int retval = lattice_set_instr(tap, LSC_INIT_ADDRESS, TAP_IDLE);
132 if (retval != ERROR_OK)
133 return retval;
134 jtag_add_runtest(2, TAP_IDLE);
135 return jtag_execute_queue();
136 }
137
138 static int lattice_certus_exit_programming_mode(struct jtag_tap *tap)
139 {
140 int retval = lattice_set_instr(tap, ISC_DISABLE, TAP_IDLE);
141 if (retval != ERROR_OK)
142 return retval;
143 jtag_add_runtest(2, TAP_IDLE);
144 retval = lattice_set_instr(tap, BYPASS, TAP_IDLE);
145 if (retval != ERROR_OK)
146 return retval;
147 jtag_add_runtest(100, TAP_IDLE);
148 return jtag_execute_queue();
149 }
150
151 static int lattice_certus_program_config_map(struct jtag_tap *tap, struct lattice_bit_file *bit_file)
152 {
153 struct scan_field field;
154
155 int retval = lattice_set_instr(tap, LSC_BITSTREAM_BURST, TAP_IDLE);
156 if (retval != ERROR_OK)
157 return retval;
158
159 field.num_bits = (bit_file->raw_bit.length - bit_file->offset) * 8;
160 field.out_value = bit_file->raw_bit.data + bit_file->offset;
161 field.in_value = NULL;
162 jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
163
164 return jtag_execute_queue();
165 }
166
167 int lattice_certus_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file)
168 {
169 struct jtag_tap *tap = lattice_device->tap;
170 if (!tap)
171 return ERROR_FAIL;
172
173 int retval = lattice_preload(lattice_device);
174 if (retval != ERROR_OK)
175 return retval;
176
177 /* check password protection is disabled */
178 const uint64_t status_pwd_protection = 0x20000;
179 retval = lattice_verify_status_register_u64(lattice_device, 0x0, 0x0, status_pwd_protection);
180 if (retval != ERROR_OK) {
181 LOG_ERROR("Password protection is set");
182 return retval;
183 }
184
185 retval = lattice_certus_enable_transparent_mode(tap);
186 if (retval != ERROR_OK)
187 return retval;
188
189 /* Check the SRAM Erase Lock */
190 const uint64_t status_otp = 0x40;
191 retval = lattice_verify_status_register_u64(lattice_device, 0x0, status_otp, status_otp);
192 if (retval != ERROR_OK) {
193 LOG_ERROR("NV User Feature Sector OTP is Set");
194 return retval;
195 }
196
197 /* Check the SRAM Lock */
198 const uint64_t status_write_protected = 0x400;
199 retval = lattice_verify_status_register_u64(lattice_device, 0x0, 0x0, status_write_protected);
200 if (retval != ERROR_OK) {
201 LOG_ERROR("NV User Feature Sector OTP is Set");
202 return retval;
203 }
204
205 retval = lattice_certus_enable_programming(tap);
206 if (retval != ERROR_OK) {
207 LOG_ERROR("failed to enable programming mode");
208 return retval;
209 }
210
211 retval = lattice_certus_erase_device(lattice_device);
212 if (retval != ERROR_OK) {
213 LOG_ERROR("erasing device failed");
214 return retval;
215 }
216
217 retval = lattice_certus_init_address(tap);
218 if (retval != ERROR_OK)
219 return retval;
220
221 retval = lattice_certus_program_config_map(tap, bit_file);
222 if (retval != ERROR_OK)
223 return retval;
224 const uint32_t expected = 0x100; // done
225 const uint32_t mask = expected |
226 0x3000 | // Busy Flag and Fail Flag
227 0xf000000; // BSE Error
228 retval = lattice_verify_status_register_u64(lattice_device, 0x0, 0x100, mask);
229 if (retval != ERROR_OK)
230 return retval;
231
232 return lattice_certus_exit_programming_mode(tap);
233 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)