1 /*
2  * Copyright (C) 2005-2019 Darron Broad
3  * All rights reserved.
4  *
5  * This file is part of Pickle Microchip PIC ICSP.
6  *
7  * Pickle Microchip PIC ICSP is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as published
9  * by the Free Software Foundation.
10  *
11  * Pickle Microchip PIC ICSP is distributed in the hope that it will be
12  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14  * Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with Pickle Microchip PIC ICSP. If not, see http://www.gnu.org/licenses/
18  */
19 
20 #undef DEBUG
21 
22 #include "pickle.h"
23 
24 /******************************************************************************
25  *
26  * Session
27  *
28  *****************************************************************************/
29 
30 extern struct pickle p;
31 
32 /*****************************************************************************
33  *
34  * Hardware operations
35  *
36  *****************************************************************************/
37 
38 struct pic_ops pic32_ops = {
39 	.arch				= ARCH32BIT,
40 	.align				= sizeof(uint32_t),
41 	.selector			= pic32_selector,
42 	.bootloader			= NULL,
43 	.program_begin			= pic32_program_begin,
44 	.program_data			= pic32_program_data,
45 	.program_end			= pic32_program_end,
46 	.verify_begin			= pic32_program_begin,
47 	.verify_data			= pic32_verify_data,
48 	.verify_end			= pic32_standby,
49 	.view_data			= pic32_view_data,
50 	.read_config_memory		= pic32_read_config_memory,
51 	.get_program_count		= pic32_get_program_count,
52 	.get_program_size		= pic32_get_program_size,
53 	.get_data_size			= NULL,
54 	.get_executive_size		= NULL,
55 	.get_boot_size			= pic32_get_boot_size,
56 	.read_program_memory_block	= pic32_read_program_memory_block,
57 	.read_data_memory_block 	= NULL,
58 	.write_panel			= pic32_write_panel,
59 	.bulk_erase			= pic32_bulk_erase,
60 	.write_osccal			= NULL,
61 	.write_bandgap			= NULL,
62 	.write_calib			= NULL,
63 	.row_erase			= NULL,
64 	.dumpdeviceid			= pic32_dumpdeviceid,
65 	.dumpconfig			= pic32_dumpconfig,
66 	.dumposccal			= NULL,
67 	.dumpdevice			= NULL,
68 	.dumpadj			= 4,
69 	.dumphexcode			= pic32_dumphexcode,
70 	.dumpinhxcode			= pic32_dumpinhxcode,
71 	.dumphexdata			= NULL,
72 	.dumpinhxdata			= NULL,
73 	.debug				= NULL,
74 };
75 
76 uint32_t
pic32_arch(void)77 pic32_arch(void)
78 {
79 	p.pic = &pic32_ops;
80 
81 	return p.pic->arch;
82 }
83 
84 /*****************************************************************************
85  *
86  * Hardware configuration
87  *
88  *****************************************************************************/
89 
90 struct pic32_config pic32_conf;
91 
92 /*****************************************************************************
93  *
94  * Hardware algorithm map: Device
95  *
96  *****************************************************************************/
97 
98 struct pic32_dsmap pic32_map[] =
99 {
100 /*Device name		Device id	 App. Data-Sheet	BOOT/PROG Size	Row/Page Size*/
101 
102 /* PIC32MX1XX/2XX DS60001168F */
103 {"PIC32MX110F016B",	PIC32MX110F016B, DS60001168F,		768, 4096,	32, 256},
104 {"PIC32MX110F016C",	PIC32MX110F016C, DS60001168F,		768, 4096,	32, 256},
105 {"PIC32MX110F016D",	PIC32MX110F016D, DS60001168F,		768, 4096,	32, 256},
106 
107 {"PIC32MX120F032B",	PIC32MX120F032B, DS60001168F,		768, 8192,	32, 256},
108 {"PIC32MX120F032C",	PIC32MX120F032C, DS60001168F,		768, 8192,	32, 256},
109 {"PIC32MX120F032D",	PIC32MX120F032D, DS60001168F,		768, 8192,	32, 256},
110 
111 {"PIC32MX130F064B",	PIC32MX130F064B, DS60001168F,		768, 16384,	32, 256},
112 {"PIC32MX130F064C",	PIC32MX130F064C, DS60001168F,		768, 16384,	32, 256},
113 {"PIC32MX130F064D",	PIC32MX130F064D, DS60001168F,		768, 16384,	32, 256},
114 
115 {"PIC32MX150F128B",	PIC32MX150F128B, DS60001168F,		768, 32768,	32, 256},
116 {"PIC32MX150F128C",	PIC32MX150F128C, DS60001168F,		768, 32768,	32, 256},
117 {"PIC32MX150F128D",	PIC32MX150F128D, DS60001168F,		768, 32768,	32, 256},
118 
119 {"PIC32MX170F256B",	PIC32MX170F256B, DS60001168F,		768, 65536,	32, 256},
120 {"PIC32MX170F256D",	PIC32MX170F256D, DS60001168F,		768, 65536,	32, 256},
121 
122 {"PIC32MX210F016B",	PIC32MX210F016B, DS60001168F,		768, 4096,	32, 256},
123 {"PIC32MX210F016C",	PIC32MX210F016C, DS60001168F,		768, 4096,	32, 256},
124 {"PIC32MX210F016D",	PIC32MX210F016D, DS60001168F,		768, 4096,	32, 256},
125 
126 {"PIC32MX220F032B",	PIC32MX220F032B, DS60001168F,		768, 8192,	32, 256},
127 {"PIC32MX220F032C",	PIC32MX220F032C, DS60001168F,		768, 8192,	32, 256},
128 {"PIC32MX220F032D",	PIC32MX220F032D, DS60001168F,		768, 8192,	32, 256},
129 
130 {"PIC32MX230F064B",	PIC32MX230F064B, DS60001168F,		768, 16384,	32, 256},
131 {"PIC32MX230F064C",	PIC32MX230F064C, DS60001168F,		768, 16384,	32, 256},
132 {"PIC32MX230F064D",	PIC32MX230F064D, DS60001168F,		768, 16384,	32, 256},
133 
134 {"PIC32MX250F128B",	PIC32MX250F128B, DS60001168F,		768, 32768,	32, 256},
135 {"PIC32MX250F128C",	PIC32MX250F128C, DS60001168F,		768, 32768,	32, 256},
136 {"PIC32MX250F128D",	PIC32MX250F128D, DS60001168F,		768, 32768,	32, 256},
137 
138 {"PIC32MX270F256B",	PIC32MX270F256B, DS60001168F,		768, 65536,	32, 256},
139 {"PIC32MX270F256D",	PIC32MX270F256D, DS60001168F,		768, 65536,	32, 256},
140 
141 /* PIC32MX330/350/370/430/450/470 DS60001185C */
142 {"PIC32MX330F064H",	PIC32MX330F064H, DS60001185C,		3072, 16384,	128, 1024},
143 {"PIC32MX330F064L",	PIC32MX330F064H, DS60001185C,		3072, 16384,	128, 1024},
144 
145 {"PIC32MX350F128H",	PIC32MX350F128H, DS60001185C,		3072, 32768,	128, 1024},
146 {"PIC32MX350F128L",	PIC32MX350F128H, DS60001185C,		3072, 32768,	128, 1024},
147 
148 {"PIC32MX350F256H",	PIC32MX350F256H, DS60001185C,		3072, 65536,	128, 1024},
149 {"PIC32MX350F256L",	PIC32MX350F256H, DS60001185C,		3072, 65536,	128, 1024},
150 
151 {"PIC32MX370F512H",	PIC32MX370F512H, DS60001185C,		3072, 131072,	128, 1024},
152 {"PIC32MX370F512L",	PIC32MX370F512H, DS60001185C,		3072, 131072,	128, 1024},
153 
154 {"PIC32MX430F064H",	PIC32MX430F064H, DS60001185C,		3072, 16384,	128, 1024},
155 {"PIC32MX430F064L",	PIC32MX430F064H, DS60001185C,		3072, 16384,	128, 1024},
156 
157 {"PIC32MX450F128H",	PIC32MX450F128H, DS60001185C,		3072, 32768,	128, 1024},
158 {"PIC32MX450F128L",	PIC32MX450F128H, DS60001185C,		3072, 32768,	128, 1024},
159 
160 {"PIC32MX450F256H",	PIC32MX450F256H, DS60001185C,		3072, 65536,	128, 1024},
161 {"PIC32MX450F256L",	PIC32MX450F256H, DS60001185C,		3072, 65536,	128, 1024},
162 
163 {"PIC32MX470F512H",	PIC32MX470F512H, DS60001185C,		3072, 131072,	128, 1024},
164 {"PIC32MX470F512L",	PIC32MX470F512H, DS60001185C,		3072, 131072,	128, 1024},
165 
166 /* PIC32MX3XX/4XX DS61143H */
167 {"PIC32MX320F032H",	PIC32MX320F032H, DS61143H,		3072, 8192,	128, 1024},
168 {"PIC32MX320F064H",	PIC32MX320F064H, DS61143H,		3072, 16384,	128, 1024},
169 {"PIC32MX320F128H",	PIC32MX320F128H, DS61143H,		3072, 32768,	128, 1024},
170 
171 {"PIC32MX340F128H",	PIC32MX340F128H, DS61143H,		3072, 32768,	128, 1024},
172 {"PIC32MX340F256H",	PIC32MX340F256H, DS61143H,		3072, 65536,	128, 1024},
173 {"PIC32MX340F512H",	PIC32MX340F512H, DS61143H,		3072, 131072,	128, 1024},
174 
175 {"PIC32MX320F128L",	PIC32MX320F128L, DS61143H,		3072, 32768,	128, 1024},
176 {"PIC32MX340F128L",	PIC32MX340F128L, DS61143H,		3072, 32768,	128, 1024},
177 
178 {"PIC32MX360F256L",	PIC32MX360F256L, DS61143H,		3072, 65536,	128, 1024},
179 {"PIC32MX360F512L",	PIC32MX360F512L, DS61143H,		3072, 131072,	128, 1024},
180 
181 {"PIC32MX420F032H",	PIC32MX420F032H, DS61143H,		3072, 8192,	128, 1024},
182 
183 {"PIC32MX440F128H",	PIC32MX440F128H, DS61143H,		3072, 32768,	128, 1024},
184 {"PIC32MX440F256H",	PIC32MX440F256H, DS61143H,		3072, 65536,	128, 1024},
185 {"PIC32MX440F512H",	PIC32MX440F512H, DS61143H,		3072, 131072,	128, 1024},
186 {"PIC32MX440F128L",	PIC32MX440F128L, DS61143H,		3072, 32768,	128, 1024},
187 
188 {"PIC32MX460F256L",	PIC32MX460F256L, DS61143H,		3072, 65536,	128, 1024},
189 {"PIC32MX460F512L",	PIC32MX460F512L, DS61143H,		3072, 131072,	128, 1024},
190 
191 /* PIC32MX5XX/6XX/7XX DS61156H */
192 {"PIC32MX534F064H",	PIC32MX534F064H, DS61156H,		3072, 16384,	128, 1024},
193 {"PIC32MX564F064H",	PIC32MX564F064H, DS61156H,		3072, 16384,	128, 1024},
194 {"PIC32MX564F128H",	PIC32MX564F128H, DS61156H,		3072, 32768,	128, 1024},
195 {"PIC32MX575F256H",	PIC32MX575F256H, DS61156H,		3072, 65536,	128, 1024},
196 {"PIC32MX575F512H",	PIC32MX575F512H, DS61156H,		3072, 131072,	128, 1024},
197 
198 {"PIC32MX534F064L",	PIC32MX534F064L, DS61156H,		3072, 16384,	128, 1024},
199 {"PIC32MX564F064L",	PIC32MX564F064L, DS61156H,		3072, 16384,	128, 1024},
200 {"PIC32MX564F128L",	PIC32MX564F128L, DS61156H,		3072, 32768,	128, 1024},
201 {"PIC32MX575F256L",	PIC32MX575F256L, DS61156H,		3072, 65536,	128, 1024},
202 {"PIC32MX575F512L",	PIC32MX575F512L, DS61156H,		3072, 131072,	128, 1024},
203 
204 {"PIC32MX664F064H",	PIC32MX664F064H, DS61156H,		3072, 16384,	128, 1024},
205 {"PIC32MX664F128H",	PIC32MX664F128H, DS61156H,		3072, 32768,	128, 1024},
206 {"PIC32MX675F256H",	PIC32MX675F256H, DS61156H,		3072, 65536,	128, 1024},
207 {"PIC32MX675F512H",	PIC32MX675F512H, DS61156H,		3072, 131072,	128, 1024},
208 {"PIC32MX695F512H",	PIC32MX695F512H, DS61156H,		3072, 131072,	128, 1024},
209 
210 {"PIC32MX664F064L",	PIC32MX664F064L, DS61156H,		3072, 16384,	128, 1024},
211 {"PIC32MX664F128L",	PIC32MX664F128L, DS61156H,		3072, 32768,	128, 1024},
212 {"PIC32MX675F256L",	PIC32MX675F256L, DS61156H,		3072, 65536,	128, 1024},
213 {"PIC32MX675F512L",	PIC32MX675F512L, DS61156H,		3072, 131072,	128, 1024},
214 {"PIC32MX695F512L",	PIC32MX695F512L, DS61156H,		3072, 131072,	128, 1024},
215 
216 {"PIC32MX764F128H",	PIC32MX764F128H, DS61156H,		3072, 32768,	128, 1024},
217 {"PIC32MX775F256H",	PIC32MX775F256H, DS61156H,		3072, 65536,	128, 1024},
218 {"PIC32MX775F512H",	PIC32MX775F512H, DS61156H,		3072, 131072,	128, 1024},
219 {"PIC32MX795F512H",	PIC32MX795F512H, DS61156H,		3072, 131072,	128, 1024},
220 
221 {"PIC32MX764F128L",	PIC32MX764F128L, DS61156H,		3072, 32768,	128, 1024},
222 {"PIC32MX775F256L",	PIC32MX775F256L, DS61156H,		3072, 65536,	128, 1024},
223 {"PIC32MX775F512L",	PIC32MX775F512L, DS61156H,		3072, 131072,	128, 1024},
224 {"PIC32MX795F512L",	PIC32MX795F512L, DS61156H,		3072, 131072,	128, 1024},
225 
226 /* PIC32MZ EC DS60001191C */
227 {"PIC32MZ1024ECG064", PIC32MZ1024ECG064, DS60001191C,		40960, 262144,	512, 4096},
228 {"PIC32MZ1024ECG100", PIC32MZ1024ECG100, DS60001191C,		40960, 262144,	512, 4096},
229 {"PIC32MZ1024ECG124", PIC32MZ1024ECG124, DS60001191C,		40960, 262144,	512, 4096},
230 {"PIC32MZ1024ECG144", PIC32MZ1024ECG144, DS60001191C,		40960, 262144,	512, 4096},
231 
232 {"PIC32MZ1024ECH064", PIC32MZ1024ECH064, DS60001191C,		40960, 262144,	512, 4096},
233 {"PIC32MZ1024ECH100", PIC32MZ1024ECH100, DS60001191C,		40960, 262144,	512, 4096},
234 {"PIC32MZ1024ECH124", PIC32MZ1024ECH124, DS60001191C,		40960, 262144,	512, 4096},
235 {"PIC32MZ1024ECH144", PIC32MZ1024ECH144, DS60001191C,		40960, 262144,	512, 4096},
236 
237 {"PIC32MZ2048ECG064", PIC32MZ2048ECG064, DS60001191C,		40960, 524288,	512, 4096},
238 {"PIC32MZ2048ECG100", PIC32MZ2048ECG100, DS60001191C,		40960, 524288,	512, 4096},
239 {"PIC32MZ2048ECG124", PIC32MZ2048ECG124, DS60001191C,		40960, 524288,	512, 4096},
240 {"PIC32MZ2048ECG144", PIC32MZ2048ECG144, DS60001191C,		40960, 524288,	512, 4096},
241 
242 {"PIC32MZ2048ECH064", PIC32MZ2048ECH064, DS60001191C,		40960, 524288,	512, 4096},
243 {"PIC32MZ2048ECH100", PIC32MZ2048ECH100, DS60001191C,		40960, 524288,	512, 4096},
244 {"PIC32MZ2048ECH124", PIC32MZ2048ECH124, DS60001191C,		40960, 524288,	512, 4096},
245 {"PIC32MZ2048ECH144", PIC32MZ2048ECH144, DS60001191C,		40960, 524288,	512, 4096},
246 
247 {"PIC32MZ1024ECM064", PIC32MZ1024ECM064, DS60001191C,		40960, 262144,	512, 4096},
248 {"PIC32MZ1024ECM100", PIC32MZ1024ECM100, DS60001191C,		40960, 262144,	512, 4096},
249 {"PIC32MZ1024ECM124", PIC32MZ1024ECM124, DS60001191C,		40960, 262144,	512, 4096},
250 {"PIC32MZ1024ECM144", PIC32MZ1024ECM144, DS60001191C,		40960, 262144,	512, 4096},
251 
252 {"PIC32MZ2048ECM064", PIC32MZ2048ECM064, DS60001191C,		40960, 524288,	512, 4096},
253 {"PIC32MZ2048ECM100", PIC32MZ2048ECM100, DS60001191C,		40960, 524288,	512, 4096},
254 {"PIC32MZ2048ECM124", PIC32MZ2048ECM124, DS60001191C,		40960, 524288,	512, 4096},
255 {"PIC32MZ2048ECM144", PIC32MZ2048ECM144, DS60001191C,		40960, 524288,	512, 4096},
256 
257 /* PIC32MX1XX/2XX/5XX 64/100-PIN FAMILY */
258 {"PIC32MX120F064H",	PIC32MX120F064H, DS60001290D,	PIC32_WORD(3),PIC32_WORD(64), 32,256},
259 {"PIC32MX130F128H",	PIC32MX130F128H, DS60001290D,	PIC32_WORD(3),PIC32_WORD(128),32,256},
260 {"PIC32MX130F128L",	PIC32MX130F128L, DS60001290D,	PIC32_WORD(3),PIC32_WORD(128),32,256},
261 {"PIC32MX230F128H",	PIC32MX230F128H, DS60001290D,	PIC32_WORD(3),PIC32_WORD(128),32,256},
262 {"PIC32MX230F128L",	PIC32MX230F128L, DS60001290D,	PIC32_WORD(3),PIC32_WORD(128),32,256},
263 {"PIC32MX530F128H",	PIC32MX530F128H, DS60001290D,	PIC32_WORD(3),PIC32_WORD(128),32,256},
264 {"PIC32MX530F128L",	PIC32MX530F128L, DS60001290D,	PIC32_WORD(3),PIC32_WORD(128),32,256},
265 {"PIC32MX150F256H",	PIC32MX150F256H, DS60001290D,	PIC32_WORD(3),PIC32_WORD(256),32,256},
266 {"PIC32MX150F256L",	PIC32MX150F256L, DS60001290D,	PIC32_WORD(3),PIC32_WORD(256),32,256},
267 {"PIC32MX250F256H",	PIC32MX250F256H, DS60001290D,	PIC32_WORD(3),PIC32_WORD(256),32,256},
268 {"PIC32MX250F256L",	PIC32MX250F256L, DS60001290D,	PIC32_WORD(3),PIC32_WORD(256),32,256},
269 {"PIC32MX550F256H",	PIC32MX550F256H, DS60001290D,	PIC32_WORD(3),PIC32_WORD(256),32,256},
270 {"PIC32MX550F256L",	PIC32MX550F256L, DS60001290D,	PIC32_WORD(3),PIC32_WORD(256),32,256},
271 {"PIC32MX170F512H",	PIC32MX170F512H, DS60001290D,	PIC32_WORD(3),PIC32_WORD(512),32,256},
272 {"PIC32MX170F512L",	PIC32MX170F512L, DS60001290D,	PIC32_WORD(3),PIC32_WORD(512),32,256},
273 {"PIC32MX270F512H",	PIC32MX270F512H, DS60001290D,	PIC32_WORD(3),PIC32_WORD(512),32,256},
274 {"PIC32MX270F512L",	PIC32MX270F512L, DS60001290D,	PIC32_WORD(3),PIC32_WORD(512),32,256},
275 {"PIC32MX570F512H",	PIC32MX570F512H, DS60001290D,	PIC32_WORD(3),PIC32_WORD(512),32,256},
276 {"PIC32MX570F512L",	PIC32MX570F512L, DS60001290D,	PIC32_WORD(3),PIC32_WORD(512),32,256},
277 
278 /* PIC32MM0016/0032/0064/0128/0256GPL0XX */
279 {"PIC32MM0016GPL020",	PIC32MM0016GPL020, DS60001324B,	PIC32_WORD(6),PIC32_WORD(16), 64,512},
280 {"PIC32MM0032GPL020",	PIC32MM0032GPL020, DS60001324B,	PIC32_WORD(6),PIC32_WORD(32), 64,512},
281 {"PIC32MM0064GPL020",	PIC32MM0064GPL020, DS60001324B,	PIC32_WORD(6),PIC32_WORD(64), 64,512},
282 {"PIC32MM0016GPL028",	PIC32MM0016GPL028, DS60001324B,	PIC32_WORD(6),PIC32_WORD(16), 64,512},
283 {"PIC32MM0032GPL028",	PIC32MM0032GPL028, DS60001324B,	PIC32_WORD(6),PIC32_WORD(32), 64,512},
284 {"PIC32MM0064GPL028",	PIC32MM0064GPL028, DS60001324B,	PIC32_WORD(6),PIC32_WORD(64), 64,512},
285 {"PIC32MM0016GPL036",	PIC32MM0016GPL036, DS60001324B,	PIC32_WORD(6),PIC32_WORD(16), 64,512},
286 {"PIC32MM0032GPL036",	PIC32MM0032GPL036, DS60001324B,	PIC32_WORD(6),PIC32_WORD(32), 64,512},
287 {"PIC32MM0064GPL036",	PIC32MM0064GPL036, DS60001324B,	PIC32_WORD(6),PIC32_WORD(64), 64,512},
288 
289 {"(null)",		0,		 0,			0, 0,		0, 0},
290 /*Device name		Device id	 App. Data-Sheet	BOOT/PROG Size	Row/Page Size*/
291 };
292 #define PIC32_SIZE ((sizeof(pic32_map) / sizeof(struct pic32_dsmap)) - 1)
293 
294 /* Default device (null) */
295 uint32_t pic32_index = PIC32_SIZE;
296 
297 void
pic32_selector(void)298 pic32_selector(void)
299 {
300 	uint32_t i;
301 	char *dnames[PIC32_SIZE];
302 
303 	for (i = 0; i < PIC32_SIZE; ++i) {
304 		dnames[i] = pic32_map[i].devicename;
305 	}
306 	qsort(dnames, PIC32_SIZE, sizeof(char *), pic_cmp);
307 	for (i = 0; i < PIC32_SIZE; ++i) {
308 		if ((i % PIC_NCOLS) == (PIC_NCOLS - 1))
309 			printf("%s\n", dnames[i]);
310 		else
311 			printf("%-19s", dnames[i]);
312 	}
313 	if (i % PIC_NCOLS)
314 		printf("\n");
315 	printf("Total: %u\n", (uint32_t)PIC32_SIZE);
316 }
317 
318 /*****************************************************************************
319  *
320  * Hardware algorithm map: Device family
321  *
322  *****************************************************************************/
323 
324 struct pic32_dstab pic32_tab[] =
325 {
326 	/* Extract PE: unzip PICKIT3.jar              */
327 
328 	/* PIC32MX1XX/2XX DS60001168F		      */
329 	{DS60001168F,	"RIPE_11_000301"},
330 
331 	/* PIC32MX330/350/370/430/450/470 DS60001185C */
332 	{DS60001185C,	"RIPE_06_000201"},
333 
334 	/* PIC32MX3XX/4XX DS61143H		      */
335 	{DS61143H,	"RIPE_06_000201"},
336 
337 	/* PIC32MX5XX/6XX/7XX DS61156H		      */
338 	{DS61156H,	"RIPE_06_000201"},
339 
340 	/* PIC32MZ EC DS60001191C		      */
341 	{DS60001191C,	"RIPE_15_000504"},
342 
343 	/* PIC32MX1XX/2XX/5XX DS60001290D             */
344 	{DS60001290D,   "RIPE_11_000301"},
345 
346 	/* PIC32MK 0512/1024                          */
347 	/* "RIPE_15a_000506"                          */
348 #if 0
349 	/* PIC32MM0016/0032/0064/0128/0256GPL0XX      */
350 	{DS60001324B,	"RIPE_20b_000510"},
351 #endif
352 	/* EOF					      */
353 	{0,		"(null)"},
354 
355 	/* DS60001145P-page 9                         */
356 	/* PIC32MK0128/0256/0512/1024 RIPE_15_aabbcc  */
357 
358 	/* DS60001145S-page 10                        */
359 	/* PIC32MX1XX/2XX/5XX         RIPE_11_aabbcc  */
360 	/* PIC32MK 0512/1024          RIPE_15a_aabbcc */
361 
362 	/* DS60001364C-page 8                         */
363 	/* PIC32MM0016/0032/0064/0128/0256GPL0XX      */
364 	/*                            RIPE_20b_aabbcc */
365 };
366 
367 /*****************************************************************************
368  *
369  * Program/Verify mode
370  *
371  *****************************************************************************/
372 
373 /*
374  * ENTER LVP PROGRAM/VERIFY MODE
375  *
376  * ENTRY - VDD FIRST
377  */
378 void
pic32_program_verify(void)379 pic32_program_verify(void)
380 {
381 	/* RESET & ACQUIRE GPIO */
382 	io_set_vpp(LOW);
383 	/* DS60001145M P6(100ns) */
384 	io_usleep(1000);
385 
386 	/* PGD + PGC + PGM(N/A) LOW */
387 	io_set_pgd(LOW);
388 	io_set_pgc(LOW);
389 	io_set_pgm(LOW);
390 	io_usleep(1000);
391 
392 	/* CONFIGURE I/O (GPIO-BB, FTDI-BB) */
393 	io_configure(TRUE, FALSE);
394 
395 	/* VPP HIGH */
396 	io_set_vpp(HIGH);
397 	/* DS60001145M P20(500us) */
398 	io_usleep(500);
399 
400 	/* VPP LOW */
401 	io_set_vpp(LOW);
402 	/* DS60001145M P18(40ns) */
403 	io_usleep(500);
404 
405 	/* PROGRAM/VERIFY ENTRY CODE */
406 	io_program_out(PHCMKEY, 32);
407 	/* DS60001145M P19(40ns) */
408 	io_usleep(500);
409 
410 	/* VPP HIGH */
411 	io_set_vpp(HIGH);
412 	/* DS60001145M P7(500ns) */
413 	io_usleep(500);
414 
415 	/* ENTER RUN-TEST/IDLE STATE */
416 	pic32_setmode(PIC32_IDLE6);
417 }
418 
419 /*
420  * EXIT LVP PROGRAM/VERIFY MODE
421  *
422  * EXIT - VDD LAST
423  */
424 void
pic32_standby(void)425 pic32_standby(void)
426 {
427 	/* ENTER TEST-LOGIC-RESET STATE */
428 	pic32_setmode(PIC32_RESET);
429 	/* DS60001145M P16(0s) */
430 	io_usleep(500);
431 
432 	/* PGD + PGC + VPP + PGM(N/A) LOW */
433 	io_set_pgd(LOW);
434 	io_set_pgc(LOW);
435 	io_set_vpp(LOW);
436 	io_set_pgm(LOW);
437 }
438 
439 /*****************************************************************************
440  *
441  * Pseudo Operations
442  *
443  *****************************************************************************/
444 
445 /*
446  * SetMode Pseudo Operation
447  *
448  *  To set the EJTAG state machine to a specific state
449  *
450  * 2-WIRE 4-PHASE
451  *
452  * DS60001145M-page 13
453  */
454 void
pic32_setmode(uint8_t nbits,uint32_t tms)455 pic32_setmode(uint8_t nbits, uint32_t tms)
456 {
457 	/* SET MODE */
458 	io_clock_bits_4phase(nbits, tms, /* tdi */ 0);
459 }
460 
461 /*
462  * SendCommand Pseudo Operation
463  *
464  *  To send a command to select a specific TAP register
465  *
466  * 2-WIRE 4-PHASE
467  *
468  * DS60001145M-page 14
469  */
470 void
pic32_sendcommand(uint8_t nbits,uint32_t tdi)471 pic32_sendcommand(uint8_t nbits, uint32_t tdi)
472 {
473 	uint32_t tms = 1UL << (nbits - 1);
474 
475 	/*
476 	 * 1. The TMS Header is clocked into the device to select the
477 	 *    Shift IR state.
478 	 */
479 
480 	/* ENTER SHIFT-IR STATE */
481 	io_clock_bit_4phase(1, 0);		/* SELECT-DR		*/
482 	io_clock_bit_4phase(1, 0);		/* SELECT-IR		*/
483 	io_clock_bit_4phase(0, 0);		/* CAPTURE-IR		*/
484 	io_clock_bit_4phase(0, 0);		/* SHIFT-IR		*/
485 
486 	/*
487 	 * 2. The command is clocked into the device on TDI while
488 	 *    holding signal TMS low.
489 	 *
490 	 * 3. The last Most Significant bit (MSb) of the command is
491 	 *    clocked in while setting TMS high.
492 	 */
493 
494 	/* SEND COMMAND */
495 	io_clock_bits_4phase(nbits,  		/* SHIFT-IR .. EXIT1-IR	*/
496 						tms, tdi);
497 	/*
498 	 * 4. The TMS Footer is clocked in on TMS to return the TAP
499 	 *    controller to the Run/Test Idle state.
500 	 */
501 
502 	/* ENTER RUN-TEST/IDLE STATE */
503 	io_clock_bit_4phase(1, 0);		/* UPDATE-IR		*/
504 	io_clock_bit_4phase(0, 0);		/* RUN-TEST/IDLE 	*/
505 }
506 
507 /*
508  * XferData Pseudo Operation
509  *
510  *  To clock data to and from the register selected by the command
511  *
512  * 2-WIRE 4-PHASE
513  *
514  * DS60001145M-page 15
515  */
516 uint32_t
pic32_xferdata(uint8_t nbits,uint32_t tdi)517 pic32_xferdata(uint8_t nbits, uint32_t tdi)
518 {
519 	uint32_t tms = 1UL << (nbits - 1);
520 	uint32_t tdo;
521 
522 	/*
523 	 * 1. The TMS Header is clocked into the device to select the
524 	 *    Shift DR state.
525 	 */
526 
527 	/* ENTER SHIFT-DR STATE */
528 	io_clock_bit_4phase(1, 0);		/* SELECT-DR		*/
529 	io_clock_bit_4phase(0, 0);		/* CAPTURE-DR		*/
530 	tdo = io_clock_bit_4phase(0, 0);	/* SHIFT-DR		*/
531 
532 	/*
533 	 * 2. The data is clocked in/out of the device on TDI/TDO while
534 	 *    holding signal TMS low.
535 	 *
536 	 * 3. The last MSb of the data is clocked in/out while setting
537 	 *    TMS high.
538 	 */
539 
540 	/* TRANSFER DATA */
541 	tdo |= io_clock_bits_4phase(nbits,	/* SHIFT-DR .. EXIT1-DR */
542 						tms, tdi) << 1;
543 	/*
544 	 * 4. The TMS Footer is clocked in on TMS to return the TAP
545 	 *    controller to the Run/Test Idle state.
546 	 */
547 
548 	/* ENTER RUN-TEST/IDLE STATE */
549 	io_clock_bit_4phase(1, 0);		/* UPDATE-DR		*/
550 	io_clock_bit_4phase(0, 0);		/* RUN-TEST/IDLE	*/
551 
552 	return tdo;
553 }
554 
555 /*
556  * XferFastData Pseudo Operation
557  *
558  *  To quickly send 32 bits of data in/out of the device
559  *
560  * 2-WIRE 4-PHASE
561  *
562  * DS60001145M-page 16
563  */
564 uint32_t
pic32_xferfastdata(uint32_t tdi)565 pic32_xferfastdata(uint32_t tdi)
566 {
567 	uint8_t pracc;
568 	uint32_t tms = 0x80000000;
569 	uint32_t tdo;
570 
571 	/*
572 	 * 1. The TMS Header is clocked into the device to select the
573 	 *    Shift DR state.
574 	 */
575 
576 	/* ENTER SHIFT-DR STATE */
577 	io_clock_bit_4phase(1, 0);		/* SELECT-DR 		*/
578 	io_clock_bit_4phase(0, 0);		/* CAPTURE-DR		*/
579 
580 	pracc = io_clock_bit_4phase(0, 0);	/* SHIFT-DR             */
581 	if (!pracc) {
582 		printf("%s: fatal error: processor access invalid [%d]\n",
583 			__func__, pracc);
584 		pic32_standby();
585 		io_exit(EX_SOFTWARE); /* Panic */
586 	}
587 
588 	/*
589 	 * 2. The input value of the PrAcc bit, which is ‘0’, is clocked
590 	 *    in.
591 	 */
592 
593 	/* PROCESSOR ACCESS */
594 	tdo = io_clock_bit_4phase(0, 0);	/* SHIFT-DR		*/
595 
596 	/* TRANSFER DATA */
597 	tdo |= io_clock_bits_4phase(32,		/* SHIFT-DR .. EXIT1-DR */
598 						tms, tdi) << 1;
599 	/*
600 	 * 3. TMS Footer = 10 is clocked in to return the TAP controller
601 	 *    to the Run/Test Idle state.
602 	 */
603 
604 	/* ENTER RUN-TEST/IDLE STATE */
605 	io_clock_bit_4phase(1, 0);		/* UPDATE-DR		*/
606 	io_clock_bit_4phase(0, 0);		/* RUN-TEST/IDLE	*/
607 
608 	return tdo;
609 }
610 
611 /*
612  * Wait until CPU is ready
613  *
614  *  Check if processor access bit is set
615  *
616  * DS60001145P-page 17
617  */
618 void
pic32_wait_for_cpu(void)619 pic32_wait_for_cpu(void)
620 {
621 	uint32_t controlVal;
622 	struct timeval tv1, tv2, tv3;
623 
624 	/* Select control register */
625 	pic32_sendcommand(PIC32_ETAP_CONTROL);
626 
627 	/* Wait until CPU is ready */
628 	gettimeofday(&tv1, NULL);
629 	do {
630 	 	/* Check if processor access bit is set */
631 		controlVal = pic32_xferdata(32,
632 			PIC32_EJTAG_CONTROL_PRACC | PIC32_EJTAG_CONTROL_PROBEN | PIC32_EJTAG_CONTROL_PROBTRAP);
633 		if (controlVal & PIC32_EJTAG_CONTROL_PRACC)
634 			return;
635 
636 		gettimeofday(&tv2, NULL);
637 		timersub(&tv2, &tv1, &tv3);
638 	}
639 	while (tv3.tv_sec < PIC_TIMEOUT);
640 
641 	printf("%s: fatal error: cpu not ready\n", __func__);
642 	pic32_standby();
643 	io_exit(EX_SOFTWARE); /* Panic */
644 }
645 
646 /*
647  * XferInstruction Pseudo Operation
648  *
649  *  To send 32 bits of data for the device to execute
650  *
651  * DS60001145M-page 18
652  */
653 uint32_t
pic32_xferinstruction(uint32_t instruction)654 pic32_xferinstruction(uint32_t instruction)
655 {
656 	uint32_t response;
657 
658 	/* Wait until CPU is ready */
659 	pic32_wait_for_cpu();
660 
661 	/* Select data register */
662 	pic32_sendcommand(PIC32_ETAP_DATA);
663 
664 	/* Send the instruction */
665 	response = pic32_xferdata(32, instruction);
666 
667 	/* Select control register */
668 	pic32_sendcommand(PIC32_ETAP_CONTROL);
669 
670 	/* Tell CPU to execute instruction */
671 	pic32_xferdata(32, PIC32_EJTAG_CONTROL_PROBEN | PIC32_EJTAG_CONTROL_PROBTRAP);
672 
673 	return response;
674 }
675 
676 /*
677  * ReadFromAddress Pseudo Operation for PIC32MX, PIC32MZ & PIC32MK devices
678  *
679  *  To read 32 bits of data from the device memory
680  *
681  * DS60001145P-page 18
682  */
683 uint32_t
pic32_readfromaddress_m4k(uint32_t addr)684 pic32_readfromaddress_m4k(uint32_t addr)
685 {
686 	uint32_t data;
687 
688 	/*
689 	 * 1. Load Fast Data register address to s3
690 	 */
691 
692 	/* LUI S3, 0xFF20 	LOAD UPPER IMMEDIATE, CLEAR LOWER */
693 	pic32_xferinstruction(0x3C13FF20);
694 
695 	/*
696 	 * 2. Load memory address to be read into t0
697 	 */
698 
699 	/* LUI T0, <Addr31:16>	LOAD UPPER IMMEDIATE, CLEAR LOWER */
700 	pic32_xferinstruction(0x3C080000 | (addr >> 16));
701 	/* ORI T0,T0 <Addr15:0>	OR LOWER IMMEDIATE */
702 	pic32_xferinstruction(0x35080000 | (addr & 0xFFFF));
703 
704 	/*
705 	 * 3. Read data
706 	 */
707 
708 	/* LW T1, 0(T0)		LOAD WORD    */
709 	pic32_xferinstruction(0x8D090000);
710 
711 	/*
712 	 * 4. Store data into Fast Data register
713 	 */
714 
715 	/* SW T1, 0(S3)		STORE WORD   */
716 	pic32_xferinstruction(0xAE690000);
717 	/* NOP                               */
718 	pic32_xferinstruction(0x00000000);
719 
720 	/*
721 	 * 5. Shift out the data
722 	 */
723 
724 	/* Select the Fastdata Register */
725 	pic32_sendcommand(PIC32_ETAP_FASTDATA);
726 
727 	/* Send/Receive 32-bit Data */
728 	data = pic32_xferfastdata(0);
729 
730 	return data;
731 }
732 
733 /*
734  * ReadFromAddress Pseudo Operation for PIC32MM devices
735  *
736  *  To read 32 bits of data from the device memory
737  *
738  * DS60001145P-page 19
739  * DS60001364C-page 17
740  */
741 uint32_t
pic32_readfromaddress_mm(uint32_t addr)742 pic32_readfromaddress_mm(uint32_t addr)
743 {
744 	uint32_t data;
745 
746 	/*
747 	 * 1. Load Fast Data register address to s3
748 	 */
749 
750 	/* LUI S3, 0xFF20 	LOAD UPPER IMMEDIATE, CLEAR LOWER */
751 	pic32_xferinstruction(0xFF2041B3);
752 
753 	/*
754 	 * 2. Load memory address to be read into t0
755 	 */
756 
757 	/* LUI T0, <Addr31:16>	LOAD UPPER IMMEDIATE, CLEAR LOWER */
758 	pic32_xferinstruction(0x000041A8 | (addr & 0xFFFF0000));
759 	/* ORI T0,T0 <Addr15:0>	OR LOWER IMMEDIATE */
760 	pic32_xferinstruction(0x00005108 | (addr << 16));
761 
762 	/*
763 	 * 3. Read data
764 	 */
765 
766 	/* LW T1, 0(T0)		LOAD WORD    */
767 	pic32_xferinstruction(0x0000FD28);
768 
769 	/*
770 	 * 4. Store data into Fast Data register
771 	 */
772 
773 	/* SW T1, 0(S3)		STORE WORD   */
774 	pic32_xferinstruction(0x0000F933);
775 	/* NOP32                             */
776 	pic32_xferinstruction(0x00000000);
777 
778 	/*
779 	 * 5. Shift out the data
780 	 */
781 
782 	/* Select the Fastdata Register */
783 	pic32_sendcommand(PIC32_ETAP_FASTDATA);
784 
785 	/* Send/Receive 32-bit Data */
786 	data = pic32_xferfastdata(0);
787 
788 	return data;
789 }
790 
791 /*
792  * Read From Address
793  */
794 static inline uint32_t
pic32_readfromaddress(uint32_t addr)795 pic32_readfromaddress(uint32_t addr)
796 {
797 	switch (pic32_map[pic32_index].datasheet) {
798 	default:return pic32_readfromaddress_m4k(addr);
799 	case DS60001324B: /* PIC32MM */
800 		return pic32_readfromaddress_mm(addr);
801 	}
802 }
803 
804 /*****************************************************************************
805  *
806  * Memory Operations
807  *
808  *****************************************************************************/
809 
810 /*
811  * Kernel KSEG1 address to physical address
812  *
813  * DS61115F-page 3-15
814  */
815 static inline uint32_t
pic32_phy(uint32_t addr)816 pic32_phy(uint32_t addr)
817 {
818 	return addr & 0x1FFFFFFF;
819 }
820 
821 /*
822  * Physical address to kernel KSEG1 address
823  *
824  * DS61115F-page 3-15
825  */
826 static inline uint32_t
pic32_kseg1(uint32_t addr)827 pic32_kseg1(uint32_t addr)
828 {
829 	return addr | 0xA0000000;
830 }
831 
832 /*****************************************************************************
833  *
834  * Utility Operations
835  *
836  *****************************************************************************/
837 
838 /*
839  * Check device status
840  *
841  * DS60001145M-page 20
842  */
843 uint32_t
pic32_check_device_status(void)844 pic32_check_device_status(void)
845 {
846 	pic32_sendcommand(PIC32_MTAP_SW_MTAP);
847 	pic32_sendcommand(PIC32_MTAP_COMMAND);
848 
849 	return pic32_xferdata(PIC32_MCHP_STATUS) & PIC32_MCHP_STATUS_MASK;
850 }
851 
852 /*
853  * Erase Device
854  *
855  * DS60001145M-page 21
856  * DS60001364C-page 20
857  */
858 static inline void
pic32_erase_device(void)859 pic32_erase_device(void)
860 {
861 	uint32_t statusVal;
862 	struct timeval tv1, tv2, tv3;
863 
864 	/*
865 	 * SendCommand (MTAP_SW_MTAP).
866 	 *
867 	 * SendCommand (MTAP_COMMAND).
868 	 *
869 	 * XferData (MCHP_ERASE).
870 	 */
871 
872 	pic32_sendcommand(PIC32_MTAP_SW_MTAP);
873 	pic32_sendcommand(PIC32_MTAP_COMMAND);
874 	pic32_xferdata(PIC32_MCHP_ERASE);
875 
876 	/*
877 	 * XferData (MCHP_DE_ASSERT_RST), not PIC32MX.
878 	 */
879 
880 	if ((pic32_map[pic32_index].datasheet == DS60001191C) ||	/* MZ EC */
881 		(pic32_map[pic32_index].datasheet == DS60001324B)) {	/* MM */
882 		pic32_xferdata(PIC32_MCHP_DE_ASSERT_RST);
883 	}
884 
885 	/*
886 	 * Delay > 10 ms.
887 	 *
888 	 * statusVal = XferData (MCHP_STATUS).
889 	 *
890 	 * If CFGRDY (statusVal<3>) is not ‘1’ and FCBUSY (statusVal<2>) is not ‘0’, GOTO to step 5.
891 	 */
892 
893 	gettimeofday(&tv1, NULL);
894 	do {
895 		/*
896 		 * Wait for "Self-Timed Page Erase Time"
897 		 *
898 		 * Eg. DS60001324B-page 214
899 		 */
900 		io_usleep(18000); /* 18 ms */
901 
902 		statusVal = pic32_xferdata(PIC32_MCHP_STATUS) & (PIC32_MCHP_STATUS_CFGRDY | PIC32_MCHP_STATUS_FCBUSY);
903 		gettimeofday(&tv2, NULL);
904 		timersub(&tv2, &tv1, &tv3);
905 	}
906 	while ((statusVal != PIC32_MCHP_STATUS_CFGRDY) && (tv3.tv_sec < PIC_TIMEOUT));
907 
908 	if (statusVal != PIC32_MCHP_STATUS_CFGRDY) {
909 		printf("%s: fatal error: erase device failed\n", __func__);
910 		pic32_standby();
911 		io_exit(EX_SOFTWARE); /* Panic */
912 	}
913 }
914 
915 /*
916  * Enter Serial Execution Mode
917  *
918  * DS60001145M-page 22
919  */
920 void
pic32_enter_serial_execution_mode(void)921 pic32_enter_serial_execution_mode(void)
922 {
923 	uint32_t statusVal;
924 
925 	statusVal = pic32_check_device_status();
926 	if (statusVal != (PIC32_MCHP_STATUS_CPS | PIC32_MCHP_STATUS_CFGRDY)) {
927 		printf("%s: fatal error: status invalid [0x%02X]\n", __func__, statusVal);
928 		pic32_standby();
929 		io_exit(EX_SOFTWARE); /* Panic */
930 	}
931 
932 	pic32_xferdata(PIC32_MCHP_ASSERT_RST);		/* 2-Wire */
933 
934 	pic32_sendcommand(PIC32_MTAP_SW_ETAP);
935 	pic32_sendcommand(PIC32_ETAP_EJTAGBOOT);
936 
937 	pic32_sendcommand(PIC32_MTAP_SW_MTAP);		/* 2-Wire ... */
938 	pic32_sendcommand(PIC32_MTAP_COMMAND);
939 
940 	pic32_xferdata(PIC32_MCHP_DE_ASSERT_RST);
941 
942 	/*
943 	 * Flash Enable, PIC32MX devices only
944 	 */
945 
946 	if ((pic32_map[pic32_index].datasheet != DS60001191C) &&	/* ! MZ EC */
947 		(pic32_map[pic32_index].datasheet != DS60001324B)) {	/* ! MM */
948 		pic32_xferdata(PIC32_MCHP_FLASH_ENABLE);
949 		statusVal = pic32_xferdata(PIC32_MCHP_STATUS) & PIC32_MCHP_STATUS_MASK;
950 		if (statusVal != (PIC32_MCHP_STATUS_CPS | PIC32_MCHP_STATUS_CFGRDY | PIC32_MCHP_STATUS_FAEN)) {
951 			printf("%s: fatal error: status invalid [0x%02X]\n", __func__, statusVal);
952 			pic32_standby();
953 			io_exit(EX_SOFTWARE); /* Panic */
954 		}
955 	}
956 
957 	pic32_sendcommand(PIC32_MTAP_SW_ETAP);
958 }
959 
960 /*****************************************************************************
961  *
962  * PE loader
963  *
964  *****************************************************************************/
965 
966 /*
967  * PIC32MX BMX
968  */
969 static void
pic32_bmx(void)970 pic32_bmx(void)
971 {
972 	/*
973 	 * PIC32MX devices only: Initialize BMXCON to 0x1F0040.
974 	 *
975 	 * lui a0,0xbf88
976 	 * ori a0,a0,0x2000 // address of BMXCON
977 	 * lui a1,0x1f
978 	 * ori a1,a1,0x40   // $a1 has 0x1f0040
979 	 * sw a1,0(a0)      // BMXCON initialized
980 	 */
981 
982 	pic32_xferinstruction(0x3c04bf88);
983 	pic32_xferinstruction(0x34842000);
984 	pic32_xferinstruction(0x3c05001f);
985 	pic32_xferinstruction(0x34a50040);
986 	pic32_xferinstruction(0xac850000);
987 
988 	/*
989 	 * PIC32MX devices only: Initialize BMXDKPBA to 0x800.
990 	 *
991 	 * li a1,0x800
992 	 * sw a1,16(a0)
993 	 */
994 
995 	pic32_xferinstruction(0x34050800);
996 	pic32_xferinstruction(0xac850010);
997 
998 	/*
999 	 * PIC32MX devices only: Initialize BMXDUDBA and BMXDUPBA to the value of BMXDRMSZ.
1000 	 *
1001 	 * lw a1,64(a0) // load BMXDMSZ
1002 	 * sw a1,32(a0)
1003 	 * sw a1,48(a0)
1004 	 */
1005 
1006 	pic32_xferinstruction(0x8C850040);
1007 	pic32_xferinstruction(0xac850020);
1008 	pic32_xferinstruction(0xac850030);
1009 }
1010 
1011 #if 0
1012 /*
1013  * Download the PE for PIC32MX, PIC32MZ & PIC32MK devices
1014  *
1015  * Custom PE loader.
1016  */
1017 void
1018 pic32_download_custom_pe_m4k(uint8_t *pe, uint32_t nbytes)
1019 {
1020 	/* PIC32MX BMX */
1021 	if (pic32_map[pic32_index].datasheet != DS60001191C) /* ! MZ EC */
1022 		pic32_bmx();
1023 
1024 	/* LUI S0, <RAM_ADDR(31:16)>   */
1025 	pic32_xferinstruction(0x3C1A0000);
1026 
1027  	/* ORI S0,S0, <RAM_ADDR(15:0)> */
1028 	pic32_xferinstruction(0x36100900);
1029 
1030 	for (uint32_t i = 0; i < nbytes; i += 4) {
1031 		/* Get low and high word data */
1032 		uint16_t datal = pe[i]     | (pe[i + 1] << 8);
1033 		uint16_t datah = pe[i + 2] | (pe[i + 3] << 8);
1034 
1035 		/* LUI T0, <Data31:16>	LOAD UPPER IMMEDIATE, CLEAR LOWER */
1036 		pic32_xferinstruction(0x3C080000 + datah);
1037 
1038 		/* ORI T0,T0 <Data15:0>	OR LOWER IMMEDIATE */
1039 		pic32_xferinstruction(0x35080000 + datal);
1040 
1041 		/* SW T0, <OFFSET>(S0)	STORE WORD */
1042 		pic32_xferinstruction(0xAE080000 + i);
1043 	}
1044 
1045 	/*
1046 	 * Jump to the PE
1047 	 *
1048 	 * lui t9,0xa000
1049 	 * ori t9,t9,0x900
1050 	 * jr t9
1051 	 * nop
1052 	 */
1053 
1054 	pic32_xferinstruction(0x3c19a000);
1055 	pic32_xferinstruction(0x37390900);
1056 	pic32_xferinstruction(0x03200008);
1057 	pic32_xferinstruction(0x00000000);
1058 }
1059 #endif
1060 
1061 /*
1062  * Download the PE for PIC32MX, PIC32MZ & PIC32MK devices
1063  *
1064  * DS60001145N-page 23
1065  */
1066 void
pic32_download_pe_m4k(uint8_t * pe,uint32_t nbytes)1067 pic32_download_pe_m4k(uint8_t *pe, uint32_t nbytes)
1068 {
1069 	/* PE LOADER OP CODES */
1070 	static uint32_t peloader[] = {
1071 		0x3c07dead, // lui a3, 0xdead
1072 		0x3c06ff20, // lui a2, 0xff20
1073 		0x3c05ff20, // lui al, 0xff20
1074 			    // here1:
1075 		0x8cc40000, // lw a0, 0 (a2)
1076 		0x8cc30000, // lw v1, 0 (a2)
1077 		0x1067000b, // beq v1, a3, <here3>
1078 		0x00000000, // nop
1079 		0x1060fffb, // beqz v1, <here1>
1080 		0x00000000, // nop
1081 			    // here2:
1082 		0x8ca20000, // lw v0, 0 (a1)
1083 		0x2463ffff, // addiu v1, v1, -1
1084 		0xac820000, // sw v0, 0 (a0)
1085 		0x24840004, // addiu a0, a0, 4
1086 		0x1460fffb, // bnez v1, <here2>
1087 		0x00000000, // nop
1088 		0x1000fff3, // b <here1>
1089 		0x00000000, // nop
1090 			    // here3:
1091 		0x3c02a000, // lui v0, 0xa000
1092 		0x34420900, // ori v0, v0, 0x900
1093 		0x00400008, // jr v0
1094 		0x00000000, // nop
1095 	};
1096 	#define PESIZE (sizeof(peloader) / sizeof(uint32_t))
1097 
1098 	/* PIC32MX BMX */
1099 	if (pic32_map[pic32_index].datasheet != DS60001191C) /* ! MZ EC */
1100 		pic32_bmx();
1101 
1102 	/*
1103 	 * Set up PIC32 RAM address for PE.
1104 	 *
1105 	 * lui a0,0xa000
1106 	 * ori a0,a0,0x800
1107 	 */
1108 
1109 	pic32_xferinstruction(0x3c04a000);
1110 	pic32_xferinstruction(0x34840800);
1111 
1112 	/*
1113 	 * Load the PE_Loader.
1114 	 *
1115 	 * lui a2, <PE_loader hi++>
1116 	 * ori a2,a2, <PE_loader lo++>
1117 	 * sw a2,0(a0)
1118 	 * addiu a0,a0,4
1119 	 */
1120 
1121 	for (uint32_t i = 0; i < PESIZE; ++i) {
1122 		uint32_t datah = peloader[i] >> 16;
1123 		uint32_t datal = peloader[i] & 0x0000FFFF;
1124 
1125 		pic32_xferinstruction(0x3c060000 + datah);
1126 		pic32_xferinstruction(0x34c60000 + datal);
1127 		pic32_xferinstruction(0xac860000);
1128 		pic32_xferinstruction(0x24840004);
1129 	}
1130 
1131 	/*
1132 	 * Jump to the PE_Loader.
1133 	 *
1134 	 * lui t9,0xa000
1135 	 * ori t9,t9,0x800
1136 	 * jr t9
1137 	 * nop
1138 	 */
1139 
1140 	pic32_xferinstruction(0x3c19a000);
1141 	pic32_xferinstruction(0x37390800);
1142 	pic32_xferinstruction(0x03200008);
1143 	pic32_xferinstruction(0x00000000);
1144 
1145 	/*
1146 	 * Load the PE using the PE_Loader.
1147 	 */
1148 
1149 	pic32_sendcommand(PIC32_ETAP_FASTDATA);
1150 	pic32_xferfastdata(pic32_kseg1(0x0900));
1151 	pic32_xferfastdata(nbytes >> 2);
1152 	for (uint32_t i = 0; i < nbytes; i += 4) {
1153 		uint32_t wdata = (uint32_t)pe[i] |
1154 		        ((uint32_t)pe[i + 1] << 8) |
1155 		        ((uint32_t)pe[i + 2] << 16) |
1156 		        ((uint32_t)pe[i + 3] << 24);
1157 		pic32_xferfastdata(wdata);
1158 	}
1159 
1160 	/*
1161 	 * Jump to the PE.
1162 	 */
1163 
1164 	pic32_xferfastdata(0x00000000);
1165 	pic32_xferfastdata(0xDEAD0000);
1166 	io_usleep(10000); /* 10ms */
1167 }
1168 
1169 #if 0
1170 /*
1171  * PIC32MM CFGCON
1172  */
1173 static void
1174 pic32_cfgcon(void)
1175 {
1176 	pic32_xferinstruction(0xBF8041A4); /* lui a0,0xbf80    */
1177 	pic32_xferinstruction(0x3B005084); /* ori a0,a0,0x3b00 */
1178 	pic32_xferinstruction(0x000041A5); /* lui a1,0x0000    */
1179 	pic32_xferinstruction(0x000050A5); /* ori a1,a1,0x0000 */
1180 	pic32_xferinstruction(0x0000F8A4); /* sw a1,0(a0)      */
1181 }
1182 #endif
1183 
1184 /*
1185  * Download the PE for PIC32MM devices
1186  *
1187  * Custom PE loader.
1188  */
1189 void
pic32_download_custom_pe_mm(uint8_t * pe,uint32_t nbytes)1190 pic32_download_custom_pe_mm(uint8_t *pe, uint32_t nbytes)
1191 {
1192 	uint32_t address = 0xA0000300;
1193 
1194 	/* LUI A0, <RAM_ADDR(31:16)> */
1195 	pic32_xferinstruction(0x41A4 | (address & 0xFFFF0000));
1196 
1197  	/* ORI A0,A0, <RAM_ADDR(15:0)> */
1198 	pic32_xferinstruction(0x5084 | (address << 16));
1199 
1200 	for (uint32_t i = 0; i < nbytes; i += 4) {
1201 		/* Get low and high word data */
1202 		uint16_t datal = pe[i]     | (pe[i + 1] << 8);
1203 		uint16_t datah = pe[i + 2] | (pe[i + 3] << 8);
1204 
1205 		/* LUI A1, <Data31:16>	LOAD UPPER IMMEDIATE, CLEAR LOWER */
1206 		pic32_xferinstruction(0x41A5 | (datah << 16));
1207 
1208 		/* ORI A1,A1 <Data15:0>	OR LOWER IMMEDIATE */
1209 		pic32_xferinstruction(0x50A5 | (datal << 16));
1210 
1211 		/* SW A1, <OFFSET>(A0)	STORE WORD */
1212 		pic32_xferinstruction(0xF8A4 | (i << 16));
1213 	}
1214 #if 1
1215 	for (uint32_t i = 0; i < nbytes; i += 4) {
1216 		uint32_t *ptr = (uint32_t *)&pe[i];
1217 		uint32_t wrote = *ptr;
1218 		uint32_t read = pic32_readfromaddress(address + i);
1219 		printf("ADDRESS=0x%08X WROTE=0x%08X READ=0x%08X\n",
1220 			address + i, wrote, read);
1221 		if (wrote != read) {
1222 			printf("FAULT\n");
1223 			pic32_standby();
1224 			io_exit(EX_SOFTWARE); /* Panic */
1225 		}
1226 	}
1227 #endif
1228 	/*
1229 	 * Jump to the PE.
1230 	 *
1231 	 * lui t9,0xXXXX
1232 	 * ori t9,t9,0xXXXX
1233 	 * jr t9; nop16
1234 	 */
1235 
1236 	pic32_xferinstruction(0x41B9 | (address & 0xFFFF0000));
1237 	pic32_xferinstruction(0x5339 | (address << 16));
1238 	pic32_xferinstruction(0x0C004599);
1239 }
1240 
1241 #if 0
1242 /*
1243  * Download the PE for PIC32MM devices
1244  *
1245  * DS60001145P-page 25
1246  * DS60001364C-page 23
1247  *
1248  * XXX DATA-SHEET INVALID
1249  */
1250 void
1251 pic32_download_pe_mm(uint8_t *pe, uint32_t nbytes)
1252 {
1253 	/* PE LOADER OP CODES */
1254 	static uint32_t peloader[] = {
1255 		0xDEAD41A7, // lui a3, 0xdead
1256 		0xFF2041A6, // lui a2, 0xff20
1257 		0xFF2041A5, // lui al, 0xff20
1258 			    // here1:
1259 		0x69E06A60, // lw a0, 0 (a2)
1260 			    // lw v1, 0 (a2)
1261 		0x000C94E3, // beq v1, a3, <here3>
1262 		0x8DFA0C00, // nop16
1263 			    // beqz v1, <here1>
1264 			    // here2:
1265 			    // lw v0, 0 (a1)
1266 		0xE9406DBE, // addiu v1, v1, -1
1267 			    // sw v0, 0 (a0)
1268 		0xADFB6E42, // addiu a0, a0, 4
1269 			    // bnez v1, <here2>
1270 		0xCFF20C00, // nop16
1271 			    // b <here1>
1272 		0x0C000C00, // nop16; nop16
1273 			    // here3:
1274 		0xA00041A2, // lui v0, 0xa000
1275 		0x03005042, // ori v0, v0, 0x300
1276 		0x0C004582, // jr v0
1277 			    // nop16
1278 	};
1279 	#define PESIZE (sizeof(peloader) / sizeof(uint32_t))
1280 
1281 printf("%s() 1\n", __func__);
1282 
1283 	/*
1284 	 * Set up the PIC32MM RAM address for the PE.
1285 	 *
1286 	 * lui a0,0xa000
1287 	 * ori a0,a0,0x200 XXX
1288 	 */
1289 
1290 	pic32_xferinstruction(0xA00041A4);
1291 	pic32_xferinstruction(0x02005084);
1292 
1293 	/*
1294 	 * Load the PE_loader.
1295 	 *
1296 	 * lui a2, <PE_loader hi++>
1297 	 * ori a2,a2, <PE_loader lo++>
1298 	 * sw a2,0(a0)
1299 	 * addiu a0,a0,4
1300 	 */
1301 
1302 	for (uint32_t i = 0; i < PESIZE; ++i) {
1303 		pic32_xferinstruction(0x41A6 | (peloader[i] & 0xFFFF0000));
1304 		pic32_xferinstruction(0x50C6 | (peloader[i] << 16));
1305 		pic32_xferinstruction(0x6E42EB40);
1306 	}
1307 
1308 	/*
1309 	 * Jump to the PE_loader.
1310 	 *
1311 	 * lui t9,0xa000
1312 	 * ori t9,t9,0x200 XXX
1313 	 * jr t9; nop16
1314 	 */
1315 
1316 	pic32_xferinstruction(0xA00041B9);
1317 	pic32_xferinstruction(0x02005339);
1318 	pic32_xferinstruction(0x0C004599);
1319 
1320 	/*
1321 	 * Load the PE using the PE_loader.
1322 	 */
1323 
1324 printf("%s() 2\n", __func__);
1325 
1326 	pic32_sendcommand(PIC32_ETAP_FASTDATA);
1327 	pic32_xferfastdata(pic32_kseg1(0x0300));
1328 	pic32_xferfastdata(nbytes >> 2);
1329 	for (uint32_t i = 0; i < nbytes; i += 4) {
1330 		uint32_t wdata = (uint32_t)pe[i] |
1331 		        ((uint32_t)pe[i + 1] << 8) |
1332 		        ((uint32_t)pe[i + 2] << 16) |
1333 		        ((uint32_t)pe[i + 3] << 24);
1334 		pic32_xferfastdata(wdata);
1335 	}
1336 
1337 	/*
1338 	 * Jump to the PE.
1339 	 */
1340 
1341 printf("%s() 3\n", __func__);
1342 
1343 	pic32_xferfastdata(0x00000000);
1344 	pic32_xferfastdata(0xDEAD0000);
1345 	io_usleep(10000); /* 10ms */
1346 }
1347 #endif
1348 
1349 /*****************************************************************************
1350  *
1351  * Download data
1352  *
1353  *****************************************************************************/
1354 
1355 /*
1356  * Download Data Block for PIC32MX, PIC32MZ & PIC32MK devices
1357  *
1358  * DS60001145M-page 25
1359  */
1360 void
pic32_download_data_block_m4k(uint32_t * panel,uint32_t panel_size)1361 pic32_download_data_block_m4k(uint32_t *panel, uint32_t panel_size)
1362 {
1363 	/*
1364 	 * Initialize SRAM Base Address to 0xA0000000.
1365 	 */
1366 
1367 	/* LUI S0, 0xA000	LOAD UPPER IMMEDIATE, CLEAR LOWER */
1368 	pic32_xferinstruction(0x3C10A000);
1369 
1370 	/*
1371 	 * Write the entire row of data to be programmed into system SRAM.
1372 	 *
1373 	 * Repeat until one row of data has been loaded.
1374 	 */
1375 
1376 	uint32_t offset = 0;
1377 	uint16_t datal, datah;
1378 	do {
1379 		/* Get low and high word data */
1380 		datal = (uint16_t)panel[offset + 0] | (uint16_t)panel[offset + 1] << 8;
1381 		datah = (uint16_t)panel[offset + 2] | (uint16_t)panel[offset + 3] << 8;
1382 
1383 		/* LUI T0, <Data31:16>	LOAD UPPER IMMEDIATE, CLEAR LOWER */
1384 		pic32_xferinstruction(0x3C080000 | datah);
1385 
1386 		/* ORI T0,T0 <Data15:0>	OR LOWER IMMEDIATE */
1387 		pic32_xferinstruction(0x35080000 | datal);
1388 
1389 		/* SW T0, <OFFSET>(S0)	STORE WORD */
1390 		pic32_xferinstruction(0xAE080000 | offset);
1391 
1392 		/* OFFSET increments by 4 */
1393 		offset += 4;
1394 	}
1395 	while (offset < panel_size);
1396 }
1397 
1398 /*
1399  * Download Data Block for PIC32MM devices
1400  *
1401  * DS60001364C-page 24
1402  */
1403 void
pic32_download_data_block_mm(uint32_t * panel,uint32_t panel_size)1404 pic32_download_data_block_mm(uint32_t *panel, uint32_t panel_size)
1405 {
1406 	/*
1407 	 * Initialize SRAM Base Address to 0xA0000000.
1408 	 */
1409 
1410 	/* LUI A0, 0xA000	LOAD UPPER IMMEDIATE, CLEAR LOWER */
1411 	pic32_xferinstruction(0xA00041A4);
1412 
1413 	/*
1414 	 * Write the entire row of data to be programmed into system SRAM.
1415 	 *
1416 	 * Repeat until one row of data has been loaded.
1417 	 */
1418 
1419 	uint32_t offset = 0;
1420 	uint16_t datal, datah;
1421 	do {
1422 		/* Get low and high word data */
1423 		datal = (uint16_t)panel[offset + 0] | (uint16_t)panel[offset + 1] << 8;
1424 		datah = (uint16_t)panel[offset + 2] | (uint16_t)panel[offset + 3] << 8;
1425 
1426 		/* LUI A1, <Data31:16>	LOAD UPPER IMMEDIATE, CLEAR LOWER */
1427 		pic32_xferinstruction(0x41A5 | (datah << 16));
1428 
1429 		/* ORI A1,A1 <Data15:0>	OR LOWER IMMEDIATE */
1430 		pic32_xferinstruction(0x50A5 | (datal << 16));
1431 
1432 		/* SW A1, <OFFSET>(A0)	STORE WORD */
1433 		pic32_xferinstruction(0xF8A4 | (offset << 16));
1434 
1435 		/* OFFSET increments by 4 */
1436 		offset += 4;
1437 	}
1438 	while (offset < panel_size);
1439 }
1440 
1441 /*
1442  * Download Data Block
1443  */
1444 static inline void
pic32_download_data_block(uint32_t * panel,uint32_t panel_size)1445 pic32_download_data_block(uint32_t *panel, uint32_t panel_size)
1446 {
1447 	switch (pic32_map[pic32_index].datasheet) {
1448 	default:pic32_download_data_block_m4k(panel, panel_size);
1449 		break;
1450 	case DS60001324B: /* PIC32MM */
1451 		pic32_download_data_block_mm(panel, panel_size);
1452 		break;
1453 	}
1454 }
1455 
1456 /*****************************************************************************
1457  *
1458  * Flash write
1459  *
1460  *****************************************************************************/
1461 
1462 /*
1463  * Flash Row Write for PIC32MX, PIC32MZ & PIC32MK devices
1464  *
1465  * DS60001145M-page 26
1466  */
1467 void
pic32_flash_row_write_m4k(uint32_t address)1468 pic32_flash_row_write_m4k(uint32_t address)
1469 {
1470 	/*
1471 	 * Registers a1, a2, and a3 are set for WREN = 1 or NVMOP<3:0> = 0011,
1472 	 * WR = 1 and WREN = 1, respectively.
1473 	 *
1474 	 * Registers s1 and s2 are set for the unlock data values and S0 is
1475 	 * initialized to ‘0’.
1476 	 */
1477 
1478 	pic32_xferinstruction(0x34054003); /* ori a1,$0,0x4003 */
1479 	pic32_xferinstruction(0x34068000); /* ori a2,$0,0x8000 */
1480 	pic32_xferinstruction(0x34074000); /* ori a3,$0,0x4000 */
1481 
1482 	pic32_xferinstruction(0x3c11aa99); /* lui s1,0xaa99    */
1483 	pic32_xferinstruction(0x36316655); /* ori s1,s1,0x6655 */
1484 	pic32_xferinstruction(0x3c125566); /* lui s2,0x5566    */
1485 	pic32_xferinstruction(0x365299aa); /* ori s2,s2,0x99aa */
1486 
1487 	/*
1488 	 * Set the physical source SRAM address
1489 	 */
1490 
1491 	pic32_xferinstruction(0x3c100000); /* lui s0,0x0000 <RAM_ADDR(31:16)> */
1492 
1493 	/*
1494 	 * PIC32MX devices only: Set register a0 to the base address of the NVM
1495 	 * register (0xBF80_F400).
1496 	 */
1497 
1498 	if (pic32_map[pic32_index].datasheet != DS60001191C) { /* ! MZ EC */
1499 		pic32_xferinstruction(0x3c04bf80); /* lui a0,0xbf80	  */
1500 		pic32_xferinstruction(0x3484f400); /* ori a0,a0,0xf400 */
1501 	}
1502 
1503 	/*
1504 	 * PIC32MZ EC devices only: Set register a0 to the base address of the
1505 	 * NVM register (0xBF80_0600).
1506 	 *
1507 	 * Register s3 is set for the value used to disable write protection in
1508 	 * NVMBPB.
1509 	 *
1510 	 * Unlock and disable Boot Flash write protection.
1511 	 */
1512 
1513 	else {
1514 		pic32_xferinstruction(0x3c04bf80); /* lui a0,0xbf80    */
1515 		pic32_xferinstruction(0x34840600); /* ori a0,a0,0x0600 */
1516 
1517 		pic32_xferinstruction(0x34138080); /* ori s3,$0,0x8080 */
1518 
1519 		pic32_xferinstruction(0xac910010); /* sw s1,16(a0)     */
1520 		pic32_xferinstruction(0xac920010); /* sw s2,16(a0)     */
1521 		pic32_xferinstruction(0xac930090); /* sw s3,144(a0)    */
1522 
1523 		pic32_xferinstruction(0x00000000); /* nop              */
1524 	}
1525 
1526 	/*
1527 	 * Set the NVMADDR register with the address of the Flash row to be programmed.
1528 	 */
1529 
1530 	uint32_t addrh = pic32_phy(address) >> 16, addrl = pic32_phy(address) & 0x0000FFFF;
1531 
1532 	pic32_xferinstruction(0x3c080000 + addrh); /* lui t0,<FLASH_ROW_ADDR(31:16)>   */
1533 	pic32_xferinstruction(0x35080000 + addrl); /* ori t0,t0,<FLASH_ROW_ADDR(15:0)> */
1534 	pic32_xferinstruction(0xac880020);         /* sw t0,32(a0)                     */
1535 
1536 	/*
1537 	 * PIC32MX devices only: Set the NVMSRCADDR register with the physical
1538 	 * source SRAM address (offset is 64).
1539 	 */
1540 
1541 	if (pic32_map[pic32_index].datasheet != DS60001191C) /* ! MZ EC */
1542 		pic32_xferinstruction(0xac900040);           /* sw s0,64(a0) */
1543 
1544 	/*
1545 	 * PIC32MZ EC devices only: Set the NVMSRCADDR register with the
1546 	 * physical source SRAM address (offset is 112).
1547 	 */
1548 
1549 	else
1550  		pic32_xferinstruction(0xac900070);           /* sw s0,112(a0) */
1551 
1552 	/*
1553 	 * Set up the NVMCON register for write operation.
1554 	 */
1555 
1556 	pic32_xferinstruction(0xac850000); /* sw a1,0(a0) */
1557 #if 0
1558 	io_usleep(6); /* Min. delay 6 us */
1559 #endif
1560 	/*
1561 	 * Unlock the NVMCON register and start the write operation.
1562 	 */
1563 
1564 	pic32_xferinstruction(0xac910010); /* sw s1,16(a0) */
1565 	pic32_xferinstruction(0xac920010); /* sw s2,16(a0) */
1566 	pic32_xferinstruction(0xac860008); /* sw a2,8(a0)  */
1567 
1568 	/*
1569 	 * Wait for "Self-Timed Row Write Cycle Time"
1570 	 *
1571 	 * Eg. DS60001324B-page 214
1572 	 */
1573 #if 0
1574 	io_usleep(1500); /* 1.5 ms */
1575 #endif
1576 	/*
1577 	 * Clear the WREN bit (NVMCONM<14>).
1578 	 */
1579 
1580 	pic32_xferinstruction(0xac870004); /* sw a3,4(a0) */
1581 }
1582 
1583 /*
1584  * Flash Row Write for PIC32MM devices
1585  *
1586  * DS60001145P-page 29
1587  * DS60001364C-page 26
1588  */
1589 void
pic32_flash_row_write_mm(uint32_t address)1590 pic32_flash_row_write_mm(uint32_t address)
1591 {
1592 	/*
1593 	 * Initialize constants. Registers a1 and a2 are set for WREN = 1 or NVMOP<3:0> = 0011
1594 	 * and WR = 1, respectively. Registers s1 and s2 are set for the unlock data values and
1595 	 * s0 is initialized to ‘0’.
1596 	 */
1597 
1598 	pic32_xferinstruction(0x400350A0); /* li a1,0x4003     */
1599 	pic32_xferinstruction(0x800050C0); /* li a2,0x8000     */
1600 
1601 	pic32_xferinstruction(0xAA9941B1); /* lui s1,0xaa99    */
1602 	pic32_xferinstruction(0x66555231); /* ori s1,s1,0x6655 */
1603 	pic32_xferinstruction(0x556641B2); /* lui s2,0x5566    */
1604 	pic32_xferinstruction(0x99AA5252); /* ori s2,s2,0x99aa */
1605 
1606 	/*
1607 	 * Set the physical source SRAM address
1608 	 */
1609 
1610 	pic32_xferinstruction(0x000041B0); /* lui s0,0x0000 <RAM_ADDR(31:16)> */
1611 
1612 	/*
1613 	 * Set register a0 to the base address of the NVM controller (0xBF80_2380). Register s3
1614 	 * is set for the value used to disable write protection in NVMBPB.
1615 	 */
1616 
1617 	pic32_xferinstruction(0xBF8041A4); /* lui a0,0xbf80    */
1618 	pic32_xferinstruction(0x23805084); /* ori a0,a0,0x2380 */
1619 	pic32_xferinstruction(0x80005260); /* li s3,0x8000 // BWPAUNLK bit mask */
1620 
1621 	/*
1622 	 * Unlock and disable Boot Flash write protection.
1623 	 */
1624 
1625 	pic32_xferinstruction(0x0010FA24); /* sw s1,16(a0)  // NVMKEY = 0xaa996655 */
1626 	pic32_xferinstruction(0x0010FA44); /* sw s2,16(a0)  // NVMKEY = 0x556699aa */
1627 	pic32_xferinstruction(0x0070FA64); /* sw s3,112(a0) // BWPAUNLK bit (NVMBPB register) = 1 */
1628 
1629 	/*
1630 	 * Set the NVMADDR register with the address of the Flash row to be programmed.
1631 	 */
1632 
1633 	pic32_xferinstruction(0x41A8 | (address & 0xFFFF0000)); /* lui t0,<FLASH_ROW_ADDR(31:16)>   */
1634 	pic32_xferinstruction(0x5108 | (address << 16));        /* ori t0,t0,<FLASH_ROW_ADDR(15:0)> */
1635 	pic32_xferinstruction(0x0020F904);                      /* sw t0,32(a0) */
1636 
1637 	/*
1638 	 * Set the NVMSRCADDR register with the physical source SRAM address.
1639 	 */
1640 
1641 	pic32_xferinstruction(0x0050FA04); /* sw s0,80(a0) */
1642 
1643 	/*
1644 	 * Set up the NVMCON register for write operation.
1645 	 */
1646 
1647 	pic32_xferinstruction(0x0C00EAC0); /* sw a1,0(a0); nop16 // NVMCON = 0x4003 */
1648 #if 0
1649 	io_usleep(6); /* Min. delay 6 us */
1650 #endif
1651 	/*
1652 	 * Unlock the NVMCON register and start the write operation (WR bit = 1).
1653 	 */
1654 
1655 	pic32_xferinstruction(0xFA44E8C4); /* sw s1,16(a0) // NVMKEY = 0xaa996655 */
1656 	pic32_xferinstruction(0xEB420010); /* sw s2,16(a0) // NVMKEY = 0x556699aa */
1657 					   /* sw a2,8(a0)  // NVMCONSET = 0x8000  */
1658 	/*
1659 	 * Wait for "Self-Timed Row Write Cycle Time"
1660 	 *
1661 	 * Eg. DS60001324B-page 214
1662 	 */
1663 #if 0
1664 	io_usleep(1500); /* 1.5 ms */
1665 #endif
1666 	/*
1667 	 * Clear the WREN bit (NVMCONM<14>).
1668 	 */
1669 
1670 	pic32_xferinstruction(0x400050E0); /* li a3,0x4000       */
1671 	pic32_xferinstruction(0x0C00EBC1); /* sw a3,4(a0); nop16 */
1672 }
1673 
1674 /*
1675  * Flash Row Write
1676  */
1677 static inline void
pic32_flash_row_write(uint32_t address)1678 pic32_flash_row_write(uint32_t address)
1679 {
1680 	switch (pic32_map[pic32_index].datasheet) {
1681 	default:pic32_flash_row_write_m4k(address);
1682 		break;
1683 	case DS60001324B: /* PIC32MM */
1684 		pic32_flash_row_write_mm(address);
1685 		break;
1686 	}
1687 }
1688 
1689 /*
1690  * Get PE Resonse
1691  *
1692  * DS60001145N-page 30
1693  */
1694 static inline uint32_t
pic32_getperesponse(void)1695 pic32_getperesponse(void)
1696 {
1697 	return pic32_xferinstruction(0x00000000);
1698 }
1699 
1700 /*****************************************************************************
1701  *
1702  * PE Commands
1703  *
1704  *****************************************************************************/
1705 
1706 /*
1707  * PE ROW PROGRAM
1708  *
1709  *  Op code 0x0
1710  *
1711  * DS60001145N-page 32
1712  */
1713 void
pic32_pe_row_program(uint32_t addr,uint32_t * panel,uint32_t panel_size)1714 pic32_pe_row_program(uint32_t addr, uint32_t *panel, uint32_t panel_size)
1715 {
1716 	/* Select the Fastdata Register */
1717 	pic32_sendcommand(PIC32_ETAP_FASTDATA);
1718 
1719 	/* Op code + Operand */
1720 	pic32_xferfastdata(panel_size >> 2);
1721 
1722 	/* PHYSICAL Address */
1723 	pic32_xferfastdata(pic32_phy(addr));
1724 
1725 	/* Data */
1726 	for (uint32_t i = 0; i < panel_size; i += 4) {
1727 		uint32_t wdata = (uint32_t)panel[i] |
1728 			((uint32_t)panel[i + 1] << 8) |
1729 			((uint32_t)panel[i + 2] << 16) |
1730 			((uint32_t)panel[i + 3] << 24);
1731 		pic32_xferfastdata(wdata);
1732 	}
1733 
1734 	/* Check response */
1735 	uint32_t rc = pic32_getperesponse();
1736 	if (rc & 0xFFFF) {
1737 		printf("%s: fatal error: PE ROW PROGRAM failed [0x%08X]\n",
1738 			__func__, rc);
1739 		pic32_standby();
1740 		io_exit(EX_SOFTWARE); /* Panic */
1741 	}
1742 }
1743 
1744 /*
1745  * PE READ
1746  *
1747  *  Op code 0x1
1748  *
1749  * DS60001145N-page 33
1750  */
1751 void
pic32_pe_read(uint32_t addr,uint16_t nwords,uint32_t * data)1752 pic32_pe_read(uint32_t addr, uint16_t nwords, uint32_t *data)
1753 {
1754 	/* Select the Fastdata Register */
1755 	pic32_sendcommand(PIC32_ETAP_FASTDATA);
1756 
1757 	/* Op code + Operand */
1758 	pic32_xferfastdata(0x00010000 + nwords);
1759 
1760 	/* KSEG1 Address */
1761 	pic32_xferfastdata(pic32_kseg1(addr));
1762 
1763 	/* Check response */
1764 	uint32_t rc = pic32_getperesponse();
1765 	if (rc != 0x00010000) {
1766 		printf("%s: fatal error: PE READ failed [0x%08X]\n",
1767 			__func__, rc);
1768 		pic32_standby();
1769 		io_exit(EX_SOFTWARE); /* Panic */
1770 	}
1771 
1772 	/* Select the Fastdata Register */
1773 	pic32_sendcommand(PIC32_ETAP_FASTDATA);
1774 
1775 	/* Get Data */
1776 	for (uint32_t i = 0; i < nwords; ++i)
1777 		data[i]	= pic32_xferfastdata(0);
1778 }
1779 
1780 /*****************************************************************************
1781  *
1782  * PE functions
1783  *
1784  *****************************************************************************/
1785 
1786 /*
1787  * PE LOAD
1788  */
1789 void
pic32_pe_load(void)1790 pic32_pe_load(void)
1791 {
1792 	uint8_t *pe = NULL;
1793 	uint32_t nbytes = 0;
1794 
1795 	/* Validate PE */
1796 	if (pic32_conf.pepath[0] == '\0') {
1797 		return;
1798 	}
1799 
1800 	/* Get PE */
1801 	pe = pic_pe_read_file(pic32_conf.pepath, &nbytes);
1802 	if (pe == NULL) {
1803 		bzero(pic32_conf.pepath, STRLEN);
1804 		return;
1805 	}
1806 
1807 	/* Download PE (upload to chip) */
1808 	switch (pic32_map[pic32_index].datasheet) {
1809 	default:pic32_download_pe_m4k(pe, nbytes);
1810 		break;
1811 	case DS60001324B: /* PIC32MM */
1812 		pic32_download_custom_pe_mm(pe, nbytes);
1813 		break;
1814 	}
1815 
1816 	/* Free PE */
1817 	free(pe);
1818 }
1819 
1820 /*
1821  * PE READ WITH CACHE
1822  */
1823 uint32_t
pic32_pe_readword(uint32_t address)1824 pic32_pe_readword(uint32_t address)
1825 {
1826 	static uint32_t cache_addr = UINT32_MAX;
1827 	static uint32_t cache_data[PIC32_PE_READWORDS];
1828 
1829 	uint32_t new_address = address & PIC32_PE_READPAGE;
1830 
1831 	if (new_address != cache_addr) {
1832 		pic32_pe_read(new_address, PIC32_PE_READWORDS, cache_data);
1833 		cache_addr = new_address;
1834 	}
1835 	return cache_data[(address >> 2) & PIC32_PE_READMASK];
1836 }
1837 
1838 /*****************************************************************************
1839  *
1840  * Compound functions
1841  *
1842  *****************************************************************************/
1843 
1844 /*
1845  * BLANK DEVICE
1846  *
1847  * DISABLE PROTECTION AND BULK ERASE
1848  */
1849 void
pic32_bulk_erase(void)1850 pic32_bulk_erase(void)
1851 {
1852 	pic32_program_verify();
1853 
1854 	pic32_erase_device();
1855 
1856 	pic32_standby();
1857 }
1858 
1859 /*****************************************************************************
1860  *
1861  * Read block data
1862  *
1863  *****************************************************************************/
1864 
1865 /*
1866  * GET CONFIGURATION
1867  */
1868 int32_t
pic32_read_config_memory(void)1869 pic32_read_config_memory(void)
1870 {
1871 	/* NULL device */
1872 	pic32_index = PIC32_SIZE;
1873 
1874 	/* Reset configuraton */
1875 	memset(&pic32_conf, 0, sizeof(pic32_conf));
1876 
1877 	pic32_program_verify();
1878 
1879 	/* Device id/rev */
1880 	pic32_conf.deviceid = pic32_xferdata(32, 0);
1881 
1882 	uint32_t dev = 0;
1883 	while (pic32_map[dev].deviceid) {
1884 		if (pic32_map[dev].deviceid == (pic32_conf.deviceid & PIC32_IDMASK))
1885 			break;
1886 		++dev;
1887 	}
1888 	if (!pic32_map[dev].deviceid) {
1889 		if (pic32_conf.deviceid == 0x00000000 || pic32_conf.deviceid == 0xFFFFFFFF) {
1890 			printf("%s: information: %s\n",
1891 				__func__, io_fault(pic32_conf.deviceid));
1892 		} else {
1893 			printf("%s: information: device unknown: [%08X]\n",
1894 				__func__, pic32_conf.deviceid);
1895 		}
1896 		pic32_standby();
1897 		return -1;
1898 	}
1899 
1900 	/* Device recognised */
1901 	pic32_index = dev;
1902 
1903 	/* Device status */
1904 	pic32_conf.status = pic32_check_device_status();
1905 	if (PIC32_MCHP_STATUS_CFGRDY != (pic32_conf.status & (PIC32_MCHP_STATUS_CFGRDY | PIC32_MCHP_STATUS_FCBUSY))) {
1906 		printf("%s: information: status invalid [0x%02X]\n", __func__, pic32_conf.status);
1907 		pic32_standby();
1908 		return -1;
1909 	}
1910 
1911 	pic32_enter_serial_execution_mode();
1912 
1913 	/* Device id/rev */
1914 	switch (pic32_map[pic32_index].datasheet) {
1915 	default:pic32_conf.devidaddr = PIC32_DEVID;
1916 		break;
1917 	case DS60001324B: /* PIC32MM */
1918 		pic32_conf.devidaddr = PIC32MM_DEVID;
1919 		break;
1920 	}
1921 
1922 	/* Device id/rev validation */
1923 	uint32_t deviceid = pic32_readfromaddress(pic32_conf.devidaddr);
1924 	if (deviceid != pic32_conf.deviceid) {
1925 		printf("%s: information: device id invalid [0x%08X] != [0x%08X]\n",
1926 			__func__, deviceid, pic32_conf.deviceid);
1927 		pic32_standby();
1928 		return -1;
1929 	}
1930 
1931 	/* Device family */
1932 	dev = 0;
1933 	while (pic32_tab[dev].datasheet) {
1934 		if (pic32_tab[dev].datasheet == pic32_map[pic32_index].datasheet) {
1935 			pic_pe_lookup(pic32_conf.pepath, pic32_tab[dev].filename);
1936 			break;
1937 		}
1938 		++dev;
1939 	}
1940 
1941 	/* Config */
1942 	switch (pic32_map[pic32_index].datasheet) {
1943 	default:pic32_conf.configaddr = PIC32_BOOT + (pic32_map[pic32_index].boot << 2) - (4 << 2);
1944 		pic32_conf.configsize = PIC32_CONFIG_SIZE;
1945 		for (uint32_t i = 0; i < pic32_conf.configsize; ++i)
1946 			pic32_conf.config[pic32_conf.configsize - 1 - i] = pic32_readfromaddress(pic32_conf.configaddr + 4 * i);
1947 		break;
1948 	case DS60001324B: /* PIC32MM */
1949 		pic32_conf.configaddr = PIC32MM_PRI_CONFIG;
1950 		pic32_conf.configsize = PIC32MM_CONFIG_SIZE;
1951 		for (uint32_t i = 0; i < pic32_conf.configsize; ++i)
1952 			pic32_conf.config[i] = pic32_readfromaddress(pic32_conf.configaddr + 4 * i);
1953 		break;
1954 	}
1955 
1956 	pic32_standby();
1957 
1958 	return 0;
1959 }
1960 
1961 /*
1962  * GET PROGRAM COUNT
1963  *
1964  *  RETURN NUMBER OF PARTITIONS
1965  */
1966 uint32_t
pic32_get_program_count(void)1967 pic32_get_program_count(void)
1968 {
1969 	return 1;
1970 }
1971 
1972 /*
1973  * GET PROGRAM FLASH SIZE
1974  *
1975  *  RETURN SIZE IN WORDS
1976  */
1977 uint32_t
pic32_get_program_size(uint32_t * addr,uint32_t partition)1978 pic32_get_program_size(uint32_t *addr, uint32_t partition)
1979 {
1980 	*addr = pic32_phy(PIC32_CODE);
1981 
1982 	return pic32_map[pic32_index].prog;
1983 }
1984 
1985 /*
1986  * GET BOOT FLASH SIZE
1987  *
1988  *  RETURN SIZE IN WORDS
1989  */
1990 uint32_t
pic32_get_boot_size(uint32_t * addr)1991 pic32_get_boot_size(uint32_t *addr)
1992 {
1993 	*addr = pic32_phy(PIC32_BOOT);
1994 
1995 	return pic32_map[pic32_index].boot;
1996 }
1997 
1998 /*
1999  * READ PROGRAM FLASH MEMORY BLOCK ADDR .. ADDR + SIZE
2000  *
2001  *  RETURN ADDR
2002  */
2003 uint32_t
pic32_read_program_memory_block(uint32_t * data,uint32_t addr,uint32_t size)2004 pic32_read_program_memory_block(uint32_t *data, uint32_t addr, uint32_t size)
2005 {
2006 	pic32_program_verify();
2007 	pic32_enter_serial_execution_mode();
2008 	pic32_pe_load();
2009 
2010 	if (pic32_conf.pepath[0]) {
2011 		/* PE */
2012 		for (uint32_t i = 0; i < size; ++i) {
2013 			data[i] = pic32_pe_readword(addr);
2014 			addr += 4;
2015 		}
2016 	} else {
2017 		/* !PE */
2018 		for (uint32_t i = 0; i < size; ++i) {
2019 			data[i] = pic32_readfromaddress(addr);
2020 			addr += 4;
2021 		}
2022 	}
2023 
2024 	pic32_standby();
2025 
2026 	return addr;
2027 }
2028 
2029 /*****************************************************************************
2030  *
2031  * Program Code
2032  *
2033  *****************************************************************************/
2034 
2035 /*
2036  * WRITE PANEL TO 32-BIT PROGRAM FLASH
2037  */
2038 void
pic32_write_panel(uint32_t region,uint32_t address,uint32_t * panel,uint32_t panel_size)2039 pic32_write_panel(uint32_t region, uint32_t address, uint32_t *panel, uint32_t panel_size)
2040 {
2041 	switch (region) {
2042 	case PIC_REGIONCODE:
2043 	case PIC_REGIONBOOT:
2044 		if (pic32_conf.pepath[0]) {
2045 			/* PE */
2046 			pic32_pe_row_program(address, panel, panel_size);
2047 		} else {
2048 			/* !PE */
2049 			pic32_download_data_block(panel, panel_size);
2050 			pic32_flash_row_write(address);
2051 		}
2052 		break;
2053 	default:printf("%s: warning: region unsupported [%d]\n", __func__, region);
2054 		break;
2055 	}
2056 }
2057 
2058 /*****************************************************************************
2059  *
2060  * Programming
2061  *
2062  *****************************************************************************/
2063 
2064 /*
2065  * DETERMINE MEMORY REGION: CODE OR BOOT
2066  *
2067  *  RETURN PIC_REGIONCODE:
2068  *	0x1D000000 .. 0x1D1FFFFF (2048KB)
2069  *
2070  *  RETURN PIC_REGIONBOOT:
2071  *  	0x1FC00000 .. 0x1FC1XXXX
2072  *
2073  * DS60001145N-page 10
2074  */
2075 uint32_t
pic32_getregion(uint32_t address)2076 pic32_getregion(uint32_t address)
2077 {
2078 	uint32_t vaddr = pic32_kseg1(address);
2079 
2080 	if (vaddr >= PIC32_CODE && vaddr < (PIC32_CODE + (pic32_map[pic32_index].prog << 2))) {
2081 		return PIC_REGIONCODE;
2082 	}
2083 	if (vaddr >= PIC32_BOOT && vaddr < (PIC32_BOOT + (pic32_map[pic32_index].boot << 2))) {
2084 		return PIC_REGIONBOOT;
2085 	}
2086 	if (p.f) fprintf(p.f, "%s: warning: address unsupported [%08X]\n",
2087 		__func__, address);
2088 	return PIC_REGIONNOTSUP;
2089 }
2090 
2091 /*
2092  * INIT REGION FOR WRITING
2093  *
2094  *  RETURN REGION IF WRITING SUPPORTED
2095  */
2096 static inline uint32_t
pic32_init_writeregion(uint32_t region)2097 pic32_init_writeregion(uint32_t region)
2098 {
2099 	switch (region) {
2100 	case PIC_REGIONCODE:
2101 	case PIC_REGIONBOOT:
2102 		pic_write_panel(PIC_PANEL_BEGIN, region, pic32_map[pic32_index].row << 2);
2103 		return region;
2104 	}
2105 	if (p.f) fprintf(p.f, "%s: warning: region unsupported [%d]\n",
2106 		__func__, region);
2107 	return PIC_REGIONNOTSUP;
2108 }
2109 
2110 /*
2111  * WRITE REGION
2112  */
2113 static inline void
pic32_writeregion(uint32_t address,uint32_t region,uint32_t data)2114 pic32_writeregion(uint32_t address, uint32_t region, uint32_t data)
2115 {
2116 	switch (region) {
2117 	case PIC_REGIONCODE:
2118 	case PIC_REGIONBOOT:
2119 		pic_write_panel(PIC_PANEL_UPDATE, address, data);
2120 		return;
2121 	}
2122 	if (p.f) fprintf(p.f, "%s: warning: region unsupported [%d]\n",
2123 		__func__, region);
2124 }
2125 
2126 /*
2127  * INIT REGION FOR VERIFY
2128  *
2129  *  RETURN REGION IF VERIFY SUPPORTED
2130  */
2131 static inline uint32_t
pic32_init_verifyregion(uint32_t region)2132 pic32_init_verifyregion(uint32_t region)
2133 {
2134 	switch (region) {
2135 	case PIC_REGIONCODE:
2136 	case PIC_REGIONBOOT:
2137 		/* Nothing to do on PIC32 */
2138 		return region;
2139 	}
2140 	if (p.f) fprintf(p.f, "%s: warning: region unsupported [%d]\n",
2141 		__func__, region);
2142 	return PIC_REGIONNOTSUP;
2143 }
2144 
2145 /*
2146  * GET VERIFY DATA FOR REGION
2147  */
2148 static inline uint32_t
pic32_verifyregion(uint32_t address,uint32_t region,uint32_t wdata)2149 pic32_verifyregion(uint32_t address, uint32_t region, uint32_t wdata)
2150 {
2151 	uint32_t vdata = 0;
2152 
2153 	if (region == PIC_REGIONNOTSUP) {
2154 		if (p.f) fprintf(p.f, "%s: warning: region unsupported [%d]\n",
2155 			__func__, region);
2156 		return wdata;
2157 	}
2158 	if (pic32_conf.pepath[0]) {
2159 		/* PE */
2160 		vdata = pic32_pe_readword(address);
2161 	} else {
2162 		/* !PE */
2163 		vdata = pic32_readfromaddress(pic32_kseg1(address));
2164 	}
2165 	return vdata;
2166 }
2167 
2168 /*****************************************************************************
2169  *
2170  * Program & verify
2171  *
2172  *****************************************************************************/
2173 
2174 /*
2175  * BEGIN PROGRAMMING
2176  */
2177 void
pic32_program_begin(void)2178 pic32_program_begin(void)
2179 {
2180 	pic32_program_verify();
2181 	pic32_enter_serial_execution_mode();
2182 	pic32_pe_load();
2183 }
2184 
2185 /*
2186  * PROGRAM DATA
2187  */
2188 uint32_t
pic32_program_data(uint32_t current_region,pic_data * pdata)2189 pic32_program_data(uint32_t current_region, pic_data *pdata)
2190 {
2191 	uint32_t address, new_region;
2192 
2193 	for (uint32_t i = 0; i < pdata->nbytes; ++i) {
2194 		address = pdata->address + i;
2195 		new_region = pic32_getregion(address);
2196 		if (new_region != current_region) {
2197 			pic_write_panel(PIC_PANEL_END, PIC_VOID, PIC_VOID);
2198 			current_region = pic32_init_writeregion(new_region);
2199 		}
2200 		if (current_region == PIC_REGIONNOTSUP)
2201 			continue;
2202 		pic32_writeregion(address, current_region, pdata->bytes[i]);
2203 	}
2204 	return current_region;
2205 }
2206 
2207 /*
2208  * END PROGRAMMING
2209  */
2210 void
pic32_program_end(int config)2211 pic32_program_end(__attribute__((unused)) int config)
2212 {
2213 	pic_write_panel(PIC_PANEL_END, PIC_VOID, PIC_VOID);
2214 	pic32_standby();
2215 }
2216 
2217 /*
2218  * VERIFY DATA
2219  */
2220 uint32_t
pic32_verify_data(uint32_t current_region,pic_data * pdata,uint32_t * fail)2221 pic32_verify_data(uint32_t current_region, pic_data *pdata, uint32_t *fail)
2222 {
2223 	uint32_t address, new_region, wdata, vdata;
2224 
2225 	for (uint32_t i = 0; i < pdata->nbytes; i += 4) {
2226 		address = pdata->address + i;
2227 		new_region = pic32_getregion(address);
2228 		if (new_region != current_region)
2229 			current_region = pic32_init_verifyregion(new_region);
2230 		if (current_region == PIC_REGIONNOTSUP)
2231 			continue;
2232 		wdata = (uint32_t)pdata->bytes[i] |
2233 			((uint32_t)pdata->bytes[i + 1] << 8) |
2234 			((uint32_t)pdata->bytes[i + 2] << 16) |
2235 			((uint32_t)pdata->bytes[i + 3] << 24);
2236 		vdata = pic32_verifyregion(address, current_region, wdata);
2237 		if (vdata != wdata) {
2238 			if (p.f) printf("%s: error: read [%08X] expected [%08X] at [%08X]\n",
2239 				__func__, vdata, wdata, pic32_phy(address));
2240 			pdata->bytes[i] = vdata;
2241 			pdata->bytes[i + 1] = vdata >> 8;
2242 			pdata->bytes[i + 2] = vdata >> 16;
2243 			pdata->bytes[i + 3] = vdata >> 24;
2244 			(*fail) += 4;
2245 		}
2246 	}
2247 	return current_region;
2248 }
2249 
2250 /*
2251  * VIEW DATA
2252  */
2253 void
pic32_view_data(pic_data * pdata)2254 pic32_view_data(pic_data *pdata)
2255 {
2256 	uint32_t wdata;
2257 
2258 	printf("[%08X] ", pdata->address);
2259 	for (uint32_t i = 0; i < pdata->nbytes; i += 4) {
2260 		wdata = (uint32_t)pdata->bytes[i] |
2261 			((uint32_t)pdata->bytes[i + 1] << 8) |
2262 			((uint32_t)pdata->bytes[i + 2] << 16) |
2263 			((uint32_t)pdata->bytes[i + 3] << 24);
2264 		printf("%08X ", wdata);
2265 	}
2266 	putchar('\n');
2267 }
2268 
2269 /*****************************************************************************
2270  *
2271  * Diagnostic functions
2272  *
2273  *****************************************************************************/
2274 
2275 /*
2276  * DUMP DEVICE ID DETAILS
2277  */
2278 void
pic32_dumpdeviceid(void)2279 pic32_dumpdeviceid(void)
2280 {
2281 	printf("[%08X] [PROGRAM]  %08X WORDS\n", pic32_phy(PIC32_CODE), pic32_map[pic32_index].prog);
2282 	printf("[%08X] [DEVICEID] %08X VER:%1X DEV:%04X MAN:%03X %s\n",
2283 		pic32_phy(pic32_conf.devidaddr),
2284 		pic32_conf.deviceid,
2285 		(pic32_conf.deviceid & 0xF0000000) >> 28,
2286 		(pic32_conf.deviceid & 0x0FFFF000) >> 12,
2287 		(pic32_conf.deviceid & 0x00000FFF),
2288 		pic32_map[pic32_index].devicename);
2289 	printf("[%08X] [BOOT]     %08X WORDS\n", pic32_phy(PIC32_BOOT), pic32_map[pic32_index].boot);
2290 	pic32_dumpconfig(PIC_BRIEF, 0);
2291 	if (pic32_conf.pepath[0]) {
2292 		char *pedup = (char *)strdup(pic32_conf.pepath);
2293 		if (pedup == NULL) {
2294 			printf("%s: fatal error: strdup failed\n", __func__);
2295 			io_exit(EX_OSERR); /* Panic */
2296 		}
2297 		printf("           [PE]       %s\n", basename(pedup));
2298 		free(pedup);
2299 	}
2300 }
2301 
2302 /*
2303  * DUMP CONFIG WORD DETAILS FOR DEVICE
2304  */
2305 void
pic32_dumpconfig(uint32_t mode,uint32_t partition)2306 pic32_dumpconfig(uint32_t mode, uint32_t partition)
2307 {
2308 	switch (pic32_map[pic32_index].datasheet) {
2309 	default:for (uint32_t i = 0; i < pic32_conf.configsize; ++i) {
2310 			printf("[%08X] [DEVCFG%d]  %08X\n", pic32_phy(pic32_conf.configaddr + 4 * i),
2311 				pic32_conf.configsize - 1 - i, pic32_conf.config[pic32_conf.configsize - 1 - i]);
2312 		}
2313 		break;
2314 	case DS60001324B: /* PIC32MM */
2315 		printf("[%08X] [RESERVED] %08X\n", pic32_phy(pic32_conf.configaddr),      pic32_conf.config[0]);
2316 		printf("[%08X] [FDEVOPT]  %08X\n", pic32_phy(pic32_conf.configaddr) + 4,  pic32_conf.config[1]);
2317 		printf("[%08X] [FICD]     %08X\n", pic32_phy(pic32_conf.configaddr) + 8,  pic32_conf.config[2]);
2318 		printf("[%08X] [FPOR]     %08X\n", pic32_phy(pic32_conf.configaddr) + 12, pic32_conf.config[3]);
2319 		printf("[%08X] [FWDT]     %08X\n", pic32_phy(pic32_conf.configaddr) + 16, pic32_conf.config[4]);
2320 		printf("[%08X] [FOCSEL]   %08X\n", pic32_phy(pic32_conf.configaddr) + 20, pic32_conf.config[5]);
2321 		printf("[%08X] [FSEC]     %08X\n", pic32_phy(pic32_conf.configaddr) + 24, pic32_conf.config[6]);
2322 		printf("[%08X] [RESERVED] %08X\n", pic32_phy(pic32_conf.configaddr) + 28, pic32_conf.config[7]);
2323 		printf("[%08X] [FSIGN]    %08X\n", pic32_phy(pic32_conf.configaddr) + 32, pic32_conf.config[8]);
2324 		printf("[%08X] [RESERVED] %08X\n", pic32_phy(pic32_conf.configaddr) + 36, pic32_conf.config[9]);
2325 	}
2326 }
2327 
2328 /*
2329  * DUMP HEX FLASH WORDS
2330  */
2331 void
pic32_dumphexcode(uint32_t address,uint32_t size,uint32_t * data)2332 pic32_dumphexcode(uint32_t address, uint32_t size, uint32_t *data)
2333 {
2334 	uint32_t i, j, nlines = 0;
2335 
2336 	for (i = 0; i < size; address += 16, i += 4) {
2337 #ifndef DEBUG
2338 		if (pic_mtcode(PIC32_MASK, 4, &data[i]))
2339 			continue;
2340 #endif
2341 		printf("[%08X] ", pic32_phy(address));
2342 		for (j = 0; j < 4; ++j) {
2343 			printf("%08X ", data[i + j]);
2344 		}
2345 		for (j = 0; j < 4; ++j) {
2346 			putchar(PIC_CHAR(0xFF & data[i + j]));
2347 			putchar(PIC_CHAR(0xFF & (data[i + j] >> 8)));
2348 			putchar(PIC_CHAR(0xFF & (data[i + j] >> 16)));
2349 			putchar(PIC_CHAR(0xFF & (data[i + j] >> 24)));
2350 		}
2351 		putchar('\n');
2352 		nlines++;
2353 	}
2354 	if (!nlines)
2355 		printf("%s: information: flash empty\n", __func__);
2356 }
2357 
2358 /*
2359  * DUMP INHX32 FLASH WORDS
2360  */
2361 void
pic32_dumpinhxcode(uint32_t address,uint32_t size,uint32_t * data)2362 pic32_dumpinhxcode(uint32_t address, uint32_t size, uint32_t *data)
2363 {
2364 	uint32_t i, j;
2365 
2366 	/* PIC32: Physical addressing */
2367 	address = pic32_phy(address);
2368 
2369 	/* PIC32: Extended address */
2370 	pic_dumpaddr(address, 1);
2371 
2372 	for (i = 0; i < size; address += 16, i += 4) {
2373 		if (pic_mtcode(PIC32_MASK, 4, &data[i]))
2374 			continue;
2375 
2376 		/* PIC32: Extended address */
2377 		pic_dumpaddr(address, 0);
2378 
2379 		uint8_t cc, b0, b1, b2, b3;
2380 		b0 = address >> 8;
2381 		b1 = address;
2382 		printf(":%02X%02X%02X00", 16, b0, b1);
2383 
2384 		cc = 16 + b0 + b1 + 0x00;
2385 		for (j = 0; j < 4; ++j) {
2386 			b0 = data[i + j];
2387 			b1 = data[i + j] >> 8;
2388 			b2 = data[i + j] >> 16;
2389 			b3 = data[i + j] >> 24;
2390 			printf("%02X%02X%02X%02X", b0, b1, b2, b3);
2391 			cc = cc + b0 + b1 + b2 + b3;
2392 		}
2393 		printf("%02X\n", (0x0100 - cc) & 0xFF);
2394 	}
2395 }
2396