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

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)