at91samd: fix protect, add EEPROM and boot commands
[fw/openocd] / src / flash / nor / at91samd.c
1 /***************************************************************************
2  *   Copyright (C) 2013 by Andrey Yurovsky                                 *
3  *   Andrey Yurovsky <yurovsky@gmail.com>                                  *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
19  ***************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "imp.h"
26 #include "helper/binarybuffer.h"
27
28 #define SAMD_NUM_SECTORS        16
29 #define SAMD_PAGE_SIZE_MAX      1024
30
31 #define SAMD_FLASH                      ((uint32_t)0x00000000)  /* physical Flash memory */
32 #define SAMD_USER_ROW           ((uint32_t)0x00804000)  /* User Row of Flash */
33 #define SAMD_PAC1                       0x41000000      /* Peripheral Access Control 1 */
34 #define SAMD_DSU                        0x41002000      /* Device Service Unit */
35 #define SAMD_NVMCTRL            0x41004000      /* Non-volatile memory controller */
36
37 #define SAMD_DSU_DID            0x18            /* Device ID register */
38
39 #define SAMD_NVMCTRL_CTRLA              0x00    /* NVM control A register */
40 #define SAMD_NVMCTRL_CTRLB              0x04    /* NVM control B register */
41 #define SAMD_NVMCTRL_PARAM              0x08    /* NVM parameters register */
42 #define SAMD_NVMCTRL_INTFLAG    0x18    /* NVM Interupt Flag Status & Clear */
43 #define SAMD_NVMCTRL_STATUS             0x18    /* NVM status register */
44 #define SAMD_NVMCTRL_ADDR               0x1C    /* NVM address register */
45 #define SAMD_NVMCTRL_LOCK               0x20    /* NVM Lock section register */
46
47 #define SAMD_CMDEX_KEY          0xA5UL
48 #define SAMD_NVM_CMD(n)         ((SAMD_CMDEX_KEY << 8) | (n & 0x7F))
49
50 /* NVMCTRL commands.  See Table 20-4 in 42129F–SAM–10/2013 */
51 #define SAMD_NVM_CMD_ER         0x02            /* Erase Row */
52 #define SAMD_NVM_CMD_WP         0x04            /* Write Page */
53 #define SAMD_NVM_CMD_EAR        0x05            /* Erase Auxilary Row */
54 #define SAMD_NVM_CMD_WAP        0x06            /* Write Auxilary Page */
55 #define SAMD_NVM_CMD_LR         0x40            /* Lock Region */
56 #define SAMD_NVM_CMD_UR         0x41            /* Unlock Region */
57 #define SAMD_NVM_CMD_SPRM       0x42            /* Set Power Reduction Mode */
58 #define SAMD_NVM_CMD_CPRM       0x43            /* Clear Power Reduction Mode */
59 #define SAMD_NVM_CMD_PBC        0x44            /* Page Buffer Clear */
60 #define SAMD_NVM_CMD_SSB        0x45            /* Set Security Bit */
61 #define SAMD_NVM_CMD_INVALL     0x46            /* Invalidate all caches */
62
63 /* Known identifiers */
64 #define SAMD_PROCESSOR_M0       0x01
65 #define SAMD_FAMILY_D           0x00
66 #define SAMD_SERIES_20          0x00
67 #define SAMD_SERIES_21          0x01
68 #define SAMD_SERIES_10          0x02
69 #define SAMD_SERIES_11          0x03
70
71 struct samd_part {
72         uint8_t id;
73         const char *name;
74         uint32_t flash_kb;
75         uint32_t ram_kb;
76 };
77
78 /* Known SAMD10 parts */
79 static const struct samd_part samd10_parts[] = {
80         { 0x0, "SAMD10D14AMU", 16, 4 },
81         { 0x1, "SAMD10D13AMU", 8, 4 },
82         { 0x2, "SAMD10D12AMU", 4, 4 },
83         { 0x3, "SAMD10D14ASU", 16, 4 },
84         { 0x4, "SAMD10D13ASU", 8, 4 },
85         { 0x5, "SAMD10D12ASU", 4, 4 },
86         { 0x6, "SAMD10C14A", 16, 4 },
87         { 0x7, "SAMD10C13A", 8, 4 },
88         { 0x8, "SAMD10C12A", 4, 4 },
89 };
90
91 /* Known SAMD11 parts */
92 static const struct samd_part samd11_parts[] = {
93         { 0x0, "SAMD11D14AMU", 16, 4 },
94         { 0x1, "SAMD11D13AMU", 8, 4 },
95         { 0x2, "SAMD11D12AMU", 4, 4 },
96         { 0x3, "SAMD11D14ASU", 16, 4 },
97         { 0x4, "SAMD11D13ASU", 8, 4 },
98         { 0x5, "SAMD11D12ASU", 4, 4 },
99         { 0x6, "SAMD11C14A", 16, 4 },
100         { 0x7, "SAMD11C13A", 8, 4 },
101         { 0x8, "SAMD11C12A", 4, 4 },
102 };
103
104 /* Known SAMD20 parts. See Table 12-8 in 42129F–SAM–10/2013 */
105 static const struct samd_part samd20_parts[] = {
106         { 0x0, "SAMD20J18A", 256, 32 },
107         { 0x1, "SAMD20J17A", 128, 16 },
108         { 0x2, "SAMD20J16A", 64, 8 },
109         { 0x3, "SAMD20J15A", 32, 4 },
110         { 0x4, "SAMD20J14A", 16, 2 },
111         { 0x5, "SAMD20G18A", 256, 32 },
112         { 0x6, "SAMD20G17A", 128, 16 },
113         { 0x7, "SAMD20G16A", 64, 8 },
114         { 0x8, "SAMD20G15A", 32, 4 },
115         { 0x9, "SAMD20G14A", 16, 2 },
116         { 0xA, "SAMD20E18A", 256, 32 },
117         { 0xB, "SAMD20E17A", 128, 16 },
118         { 0xC, "SAMD20E16A", 64, 8 },
119         { 0xD, "SAMD20E15A", 32, 4 },
120         { 0xE, "SAMD20E14A", 16, 2 },
121 };
122
123 /* Known SAMD21 parts. */
124 static const struct samd_part samd21_parts[] = {
125         { 0x0, "SAMD21J18A", 256, 32 },
126         { 0x1, "SAMD21J17A", 128, 16 },
127         { 0x2, "SAMD21J16A", 64, 8 },
128         { 0x3, "SAMD21J15A", 32, 4 },
129         { 0x4, "SAMD21J14A", 16, 2 },
130         { 0x5, "SAMD21G18A", 256, 32 },
131         { 0x6, "SAMD21G17A", 128, 16 },
132         { 0x7, "SAMD21G16A", 64, 8 },
133         { 0x8, "SAMD21G15A", 32, 4 },
134         { 0x9, "SAMD21G14A", 16, 2 },
135         { 0xA, "SAMD21E18A", 256, 32 },
136         { 0xB, "SAMD21E17A", 128, 16 },
137         { 0xC, "SAMD21E16A", 64, 8 },
138         { 0xD, "SAMD21E15A", 32, 4 },
139         { 0xE, "SAMD21E14A", 16, 2 },
140 };
141
142 /* Known SAMR21 parts. */
143 static const struct samd_part samr21_parts[] = {
144         { 0x19, "SAMR21G18A", 256, 32 },
145         { 0x1A, "SAMR21G17A", 128, 32 },
146         { 0x1B, "SAMR21G16A",  64, 32 },
147         { 0x1C, "SAMR21E18A", 256, 32 },
148         { 0x1D, "SAMR21E17A", 128, 32 },
149         { 0x1E, "SAMR21E16A",  64, 32 },
150 };
151
152
153 /* Each family of parts contains a parts table in the DEVSEL field of DID.  The
154  * processor ID, family ID, and series ID are used to determine which exact
155  * family this is and then we can use the corresponding table. */
156 struct samd_family {
157         uint8_t processor;
158         uint8_t family;
159         uint8_t series;
160         const struct samd_part *parts;
161         size_t num_parts;
162 };
163
164 /* Known SAMD families */
165 static const struct samd_family samd_families[] = {
166         { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_20,
167                 samd20_parts, ARRAY_SIZE(samd20_parts) },
168         { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_21,
169                 samd21_parts, ARRAY_SIZE(samd21_parts) },
170         { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_21,
171                 samr21_parts, ARRAY_SIZE(samr21_parts) },
172         { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_10,
173                 samd10_parts, ARRAY_SIZE(samd10_parts) },
174         { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_11,
175                 samd11_parts, ARRAY_SIZE(samd11_parts) },
176 };
177
178 struct samd_info {
179         uint32_t page_size;
180         int num_pages;
181         int sector_size;
182
183         bool probed;
184         struct target *target;
185         struct samd_info *next;
186 };
187
188 static struct samd_info *samd_chips;
189
190 static const struct samd_part *samd_find_part(uint32_t id)
191 {
192         uint8_t processor = (id >> 28);
193         uint8_t family = (id >> 24) & 0x0F;
194         uint8_t series = (id >> 16) & 0xFF;
195         uint8_t devsel = id & 0xFF;
196
197         for (unsigned i = 0; i < ARRAY_SIZE(samd_families); i++) {
198                 if (samd_families[i].processor == processor &&
199                         samd_families[i].series == series &&
200                         samd_families[i].family == family) {
201                         for (unsigned j = 0; j < samd_families[i].num_parts; j++) {
202                                 if (samd_families[i].parts[j].id == devsel)
203                                         return &samd_families[i].parts[j];
204                         }
205                 }
206         }
207
208         return NULL;
209 }
210
211 static int samd_protect_check(struct flash_bank *bank)
212 {
213         int res;
214         uint16_t lock;
215
216         res = target_read_u16(bank->target,
217                         SAMD_NVMCTRL + SAMD_NVMCTRL_LOCK, &lock);
218         if (res != ERROR_OK)
219                 return res;
220
221         /* Lock bits are active-low */
222         for (int i = 0; i < bank->num_sectors; i++)
223                 bank->sectors[i].is_protected = !(lock & (1<<i));
224
225         return ERROR_OK;
226 }
227
228 static int samd_get_flash_page_info(struct target *target,
229                 uint32_t *sizep, int *nump)
230 {
231         int res;
232         uint32_t param;
233
234         res = target_read_u32(target, SAMD_NVMCTRL + SAMD_NVMCTRL_PARAM, &param);
235         if (res == ERROR_OK) {
236                 /* The PSZ field (bits 18:16) indicate the page size bytes as 2^(3+n)
237                  * so 0 is 8KB and 7 is 1024KB. */
238                 if (sizep)
239                         *sizep = (8 << ((param >> 16) & 0x7));
240                 /* The NVMP field (bits 15:0) indicates the total number of pages */
241                 if (nump)
242                         *nump = param & 0xFFFF;
243         } else {
244                 LOG_ERROR("Couldn't read NVM Parameters register");
245         }
246
247         return res;
248 }
249
250 static int samd_probe(struct flash_bank *bank)
251 {
252         uint32_t id;
253         int res;
254         struct samd_info *chip = (struct samd_info *)bank->driver_priv;
255         const struct samd_part *part;
256
257         if (chip->probed)
258                 return ERROR_OK;
259
260         res = target_read_u32(bank->target, SAMD_DSU + SAMD_DSU_DID, &id);
261         if (res != ERROR_OK) {
262                 LOG_ERROR("Couldn't read Device ID register");
263                 return res;
264         }
265
266         part = samd_find_part(id);
267         if (part == NULL) {
268                 LOG_ERROR("Couldn't find part correspoding to DID %08" PRIx32, id);
269                 return ERROR_FAIL;
270         }
271
272         bank->size = part->flash_kb * 1024;
273
274         chip->sector_size = bank->size / SAMD_NUM_SECTORS;
275
276         res = samd_get_flash_page_info(bank->target, &chip->page_size,
277                         &chip->num_pages);
278         if (res != ERROR_OK) {
279                 LOG_ERROR("Couldn't determine Flash page size");
280                 return res;
281         }
282
283         /* Sanity check: the total flash size in the DSU should match the page size
284          * multiplied by the number of pages. */
285         if (bank->size != chip->num_pages * chip->page_size) {
286                 LOG_WARNING("SAMD: bank size doesn't match NVM parameters. "
287                                 "Identified %" PRIu32 "KB Flash but NVMCTRL reports %u %" PRIu32 "B pages",
288                                 part->flash_kb, chip->num_pages, chip->page_size);
289         }
290
291         /* Allocate the sector table */
292         bank->num_sectors = SAMD_NUM_SECTORS;
293         bank->sectors = calloc(bank->num_sectors, sizeof((bank->sectors)[0]));
294         if (!bank->sectors)
295                 return ERROR_FAIL;
296
297         /* Fill out the sector information: all SAMD sectors are the same size and
298          * there is always a fixed number of them. */
299         for (int i = 0; i < bank->num_sectors; i++) {
300                 bank->sectors[i].size = chip->sector_size;
301                 bank->sectors[i].offset = i * chip->sector_size;
302                 /* mark as unknown */
303                 bank->sectors[i].is_erased = -1;
304                 bank->sectors[i].is_protected = -1;
305         }
306
307         samd_protect_check(bank);
308
309         /* Done */
310         chip->probed = true;
311
312         LOG_INFO("SAMD MCU: %s (%" PRIu32 "KB Flash, %" PRIu32 "KB RAM)", part->name,
313                         part->flash_kb, part->ram_kb);
314
315         return ERROR_OK;
316 }
317
318 static bool samd_check_error(struct target *target)
319 {
320         int ret;
321         bool error;
322         uint16_t status;
323
324         ret = target_read_u16(target,
325                         SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, &status);
326         if (ret != ERROR_OK) {
327                 LOG_ERROR("Can't read NVM status");
328                 return true;
329         }
330
331         if (status & 0x001C) {
332                 if (status & (1 << 4)) /* NVME */
333                         LOG_ERROR("SAMD: NVM Error");
334                 if (status & (1 << 3)) /* LOCKE */
335                         LOG_ERROR("SAMD: NVM lock error");
336                 if (status & (1 << 2)) /* PROGE */
337                         LOG_ERROR("SAMD: NVM programming error");
338
339                 error = true;
340         } else {
341                 error = false;
342         }
343
344         /* Clear the error conditions by writing a one to them */
345         ret = target_write_u16(target,
346                         SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, status);
347         if (ret != ERROR_OK)
348                 LOG_ERROR("Can't clear NVM error conditions");
349
350         return error;
351 }
352
353 static int samd_issue_nvmctrl_command(struct target *target, uint16_t cmd)
354 {
355         if (target->state != TARGET_HALTED) {
356                 LOG_ERROR("Target not halted");
357                 return ERROR_TARGET_NOT_HALTED;
358         }
359
360         /* Read current configuration. */
361         uint16_t tmp = 0;
362         int res = target_read_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB,
363                         &tmp);
364         if (res != ERROR_OK)
365                 return res;
366
367         /* Set cache disable. */
368         res = target_write_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB,
369                         tmp | (1<<18));
370         if (res != ERROR_OK)
371                 return res;
372
373         /* Issue the NVM command */
374         int res_cmd = target_write_u16(target,
375                         SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLA, SAMD_NVM_CMD(cmd));
376
377         /* Try to restore configuration, regardless of NVM command write
378          * status. */
379         res = target_write_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB, tmp);
380
381         if (res_cmd != ERROR_OK)
382                 return res_cmd;
383
384         if (res != ERROR_OK)
385                 return res;
386
387         /* Check to see if the NVM command resulted in an error condition. */
388         if (samd_check_error(target))
389                 return ERROR_FAIL;
390
391         return ERROR_OK;
392 }
393
394 static int samd_erase_row(struct target *target, uint32_t address)
395 {
396         int res;
397
398         /* Set an address contained in the row to be erased */
399         res = target_write_u32(target,
400                         SAMD_NVMCTRL + SAMD_NVMCTRL_ADDR, address >> 1);
401
402         /* Issue the Erase Row command to erase that row. */
403         if (res == ERROR_OK)
404                 res = samd_issue_nvmctrl_command(target,
405                                 address == SAMD_USER_ROW ? SAMD_NVM_CMD_EAR : SAMD_NVM_CMD_ER);
406
407         if (res != ERROR_OK)  {
408                 LOG_ERROR("Failed to erase row containing %08" PRIx32, address);
409                 return ERROR_FAIL;
410         }
411
412         return ERROR_OK;
413 }
414
415 static bool is_user_row_reserved_bit(uint8_t bit)
416 {
417         /* See Table 9-3 in the SAMD20 datasheet for more information. */
418         switch (bit) {
419                 /* Reserved bits */
420                 case 3:
421                 case 7:
422                 /* Voltage regulator internal configuration with default value of 0x70,
423                  * may not be changed. */
424                 case 17 ... 24:
425                 /* 41 is voltage regulator internal configuration and must not be
426                  * changed.  42 through 47 are reserved. */
427                 case 41 ... 47:
428                         return true;
429                 default:
430                         break;
431         }
432
433         return false;
434 }
435
436 /* Modify the contents of the User Row in Flash.  These are described in Table
437  * 9-3 of the SAMD20 datasheet.  The User Row itself has a size of one page
438  * and contains a combination of "fuses" and calibration data in bits 24:17.
439  * We therefore try not to erase the row's contents unless we absolutely have
440  * to and we don't permit modifying reserved bits. */
441 static int samd_modify_user_row(struct target *target, uint32_t value,
442                 uint8_t startb, uint8_t endb)
443 {
444         int res;
445
446         if (is_user_row_reserved_bit(startb) || is_user_row_reserved_bit(endb)) {
447                 LOG_ERROR("Can't modify bits in the requested range");
448                 return ERROR_FAIL;
449         }
450
451         /* Retrieve the MCU's page size, in bytes. This is also the size of the
452          * entire User Row. */
453         uint32_t page_size;
454         res = samd_get_flash_page_info(target, &page_size, NULL);
455         if (res != ERROR_OK) {
456                 LOG_ERROR("Couldn't determine Flash page size");
457                 return res;
458         }
459
460         /* Make sure the size is sane before we allocate. */
461         assert(page_size > 0 && page_size <= SAMD_PAGE_SIZE_MAX);
462
463         /* Make sure we're within the single page that comprises the User Row. */
464         if (startb >= (page_size * 8) || endb >= (page_size * 8)) {
465                 LOG_ERROR("Can't modify bits outside the User Row page range");
466                 return ERROR_FAIL;
467         }
468
469         uint8_t *buf = malloc(page_size);
470         if (!buf)
471                 return ERROR_FAIL;
472
473         /* Read the user row (comprising one page) by half-words. */
474         res = target_read_memory(target, SAMD_USER_ROW, 2, page_size / 2, buf);
475         if (res != ERROR_OK)
476                 goto out_user_row;
477
478         /* We will need to erase before writing if the new value needs a '1' in any
479          * position for which the current value had a '0'.  Otherwise we can avoid
480          * erasing. */
481         uint32_t cur = buf_get_u32(buf, startb, endb - startb + 1);
482         if ((~cur) & value) {
483                 res = samd_erase_row(target, SAMD_USER_ROW);
484                 if (res != ERROR_OK) {
485                         LOG_ERROR("Couldn't erase user row");
486                         goto out_user_row;
487                 }
488         }
489
490         /* Modify */
491         buf_set_u32(buf, startb, endb - startb + 1, value);
492
493         /* Write the page buffer back out to the target.  A Flash write will be
494          * triggered automatically. */
495         res = target_write_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf);
496         if (res != ERROR_OK)
497                 goto out_user_row;
498
499         if (samd_check_error(target)) {
500                 res = ERROR_FAIL;
501                 goto out_user_row;
502         }
503
504         /* Success */
505         res = ERROR_OK;
506
507 out_user_row:
508         free(buf);
509
510         return res;
511 }
512
513 static int samd_protect(struct flash_bank *bank, int set, int first, int last)
514 {
515         struct samd_info *chip = (struct samd_info *)bank->driver_priv;
516
517         /* We can issue lock/unlock region commands with the target running but
518          * the settings won't persist unless we're able to modify the LOCK regions
519          * and that requires the target to be halted. */
520         if (bank->target->state != TARGET_HALTED) {
521                 LOG_ERROR("Target not halted");
522                 return ERROR_TARGET_NOT_HALTED;
523         }
524
525         int res = ERROR_OK;
526
527         for (int s = first; s <= last; s++) {
528                 if (set != bank->sectors[s].is_protected) {
529                         /* Load an address that is within this sector (we use offset 0) */
530                         res = target_write_u32(bank->target,
531                                                         SAMD_NVMCTRL + SAMD_NVMCTRL_ADDR,
532                                                         ((s * chip->sector_size) >> 1));
533                         if (res != ERROR_OK)
534                                 goto exit;
535
536                         /* Tell the controller to lock that sector */
537                         res = samd_issue_nvmctrl_command(bank->target,
538                                         set ? SAMD_NVM_CMD_LR : SAMD_NVM_CMD_UR);
539                         if (res != ERROR_OK)
540                                 goto exit;
541                 }
542         }
543
544         /* We've now applied our changes, however they will be undone by the next
545          * reset unless we also apply them to the LOCK bits in the User Page.  The
546          * LOCK bits start at bit 48, correspoding to Sector 0 and end with bit 63,
547          * corresponding to Sector 15.  A '1' means unlocked and a '0' means
548          * locked.  See Table 9-3 in the SAMD20 datasheet for more details. */
549
550         res = samd_modify_user_row(bank->target, set ? 0x0000 : 0xFFFF,
551                         48 + first, 48 + last);
552         if (res != ERROR_OK)
553                 LOG_WARNING("SAMD: protect settings were not made persistent!");
554
555         res = ERROR_OK;
556
557 exit:
558         samd_protect_check(bank);
559
560         return res;
561 }
562
563 static int samd_erase(struct flash_bank *bank, int first, int last)
564 {
565         int res;
566         int rows_in_sector;
567         struct samd_info *chip = (struct samd_info *)bank->driver_priv;
568
569         if (bank->target->state != TARGET_HALTED) {
570                 LOG_ERROR("Target not halted");
571
572                 return ERROR_TARGET_NOT_HALTED;
573         }
574
575         if (!chip->probed) {
576                 if (samd_probe(bank) != ERROR_OK)
577                         return ERROR_FLASH_BANK_NOT_PROBED;
578         }
579
580         /* The SAMD NVM has row erase granularity.  There are four pages in a row
581          * and the number of rows in a sector depends on the sector size, which in
582          * turn depends on the Flash capacity as there is a fixed number of
583          * sectors. */
584         rows_in_sector = chip->sector_size / (chip->page_size * 4);
585
586         /* For each sector to be erased */
587         for (int s = first; s <= last; s++) {
588                 if (bank->sectors[s].is_protected) {
589                         LOG_ERROR("SAMD: failed to erase sector %d. That sector is write-protected", s);
590                         return ERROR_FLASH_OPERATION_FAILED;
591                 }
592
593                 if (!bank->sectors[s].is_erased) {
594                         /* For each row in that sector */
595                         for (int r = s * rows_in_sector; r < (s + 1) * rows_in_sector; r++) {
596                                 res = samd_erase_row(bank->target, r * chip->page_size * 4);
597                                 if (res != ERROR_OK) {
598                                         LOG_ERROR("SAMD: failed to erase sector %d", s);
599                                         return res;
600                                 }
601                         }
602
603                         bank->sectors[s].is_erased = 1;
604                 }
605         }
606
607         return ERROR_OK;
608 }
609
610 static struct flash_sector *samd_find_sector_by_address(struct flash_bank *bank, uint32_t address)
611 {
612         struct samd_info *chip = (struct samd_info *)bank->driver_priv;
613
614         for (int i = 0; i < bank->num_sectors; i++) {
615                 if (bank->sectors[i].offset <= address &&
616                     address < bank->sectors[i].offset + chip->sector_size)
617                         return &bank->sectors[i];
618         }
619         return NULL;
620 }
621
622 /* Write an entire row (four pages) from host buffer 'buf' to row-aligned
623  * 'address' in the Flash. */
624 static int samd_write_row(struct flash_bank *bank, uint32_t address,
625                 const uint8_t *buf)
626 {
627         int res;
628         struct samd_info *chip = (struct samd_info *)bank->driver_priv;
629
630         struct flash_sector *sector = samd_find_sector_by_address(bank, address);
631
632         if (!sector) {
633                 LOG_ERROR("Can't find sector corresponding to address 0x%08" PRIx32, address);
634                 return ERROR_FLASH_OPERATION_FAILED;
635         }
636
637         if (sector->is_protected) {
638                 LOG_ERROR("Trying to write to a protected sector at 0x%08" PRIx32, address);
639                 return ERROR_FLASH_OPERATION_FAILED;
640         }
641
642         /* Erase the row that we'll be writing to */
643         res = samd_erase_row(bank->target, address);
644         if (res != ERROR_OK)
645                 return res;
646
647         /* Now write the pages in this row. */
648         for (unsigned int i = 0; i < 4; i++) {
649                 bool error;
650
651                 /* Write the page contents to the target's page buffer.  A page write
652                  * is issued automatically once the last location is written in the
653                  * page buffer (ie: a complete page has been written out). */
654                 res = target_write_memory(bank->target, address, 4,
655                                 chip->page_size / 4, buf);
656                 if (res != ERROR_OK) {
657                         LOG_ERROR("%s: %d", __func__, __LINE__);
658                         return res;
659                 }
660
661                 error = samd_check_error(bank->target);
662                 if (error)
663                         return ERROR_FAIL;
664
665                 /* Next page */
666                 address += chip->page_size;
667                 buf += chip->page_size;
668         }
669
670         sector->is_erased = 0;
671
672         return res;
673 }
674
675 /* Write partial contents into row-aligned 'address' on the Flash from host
676  * buffer 'buf' by writing 'nb' of 'buf' at 'row_offset' into the Flash row. */
677 static int samd_write_row_partial(struct flash_bank *bank, uint32_t address,
678                 const uint8_t *buf, uint32_t row_offset, uint32_t nb)
679 {
680         int res;
681         struct samd_info *chip = (struct samd_info *)bank->driver_priv;
682         uint32_t row_size = chip->page_size * 4;
683         uint8_t *rb = malloc(row_size);
684         if (!rb)
685                 return ERROR_FAIL;
686
687         assert(row_offset + nb < row_size);
688         assert((address % row_size) == 0);
689
690         /* Retrieve the full row contents from Flash */
691         res = target_read_memory(bank->target, address, 4, row_size / 4, rb);
692         if (res != ERROR_OK) {
693                 free(rb);
694                 return res;
695         }
696
697         /* Insert our partial row over the data from Flash */
698         memcpy(rb + (row_offset % row_size), buf, nb);
699
700         /* Write the row back out */
701         res = samd_write_row(bank, address, rb);
702         free(rb);
703
704         return res;
705 }
706
707 static int samd_write(struct flash_bank *bank, const uint8_t *buffer,
708                 uint32_t offset, uint32_t count)
709 {
710         int res;
711         uint32_t address;
712         uint32_t nb = 0;
713         struct samd_info *chip = (struct samd_info *)bank->driver_priv;
714         uint32_t row_size = chip->page_size * 4;
715
716         if (bank->target->state != TARGET_HALTED) {
717                 LOG_ERROR("Target not halted");
718
719                 return ERROR_TARGET_NOT_HALTED;
720         }
721
722         if (!chip->probed) {
723                 if (samd_probe(bank) != ERROR_OK)
724                         return ERROR_FLASH_BANK_NOT_PROBED;
725         }
726
727         if (offset % row_size) {
728                 /* We're starting at an unaligned offset so we'll write a partial row
729                  * comprising that offset and up to the end of that row. */
730                 nb = row_size - (offset % row_size);
731                 if (nb > count)
732                         nb = count;
733         } else if (count < row_size) {
734                 /* We're writing an aligned but partial row. */
735                 nb = count;
736         }
737
738         address = (offset / row_size) * row_size + bank->base;
739
740         if (nb > 0) {
741                 res = samd_write_row_partial(bank, address, buffer,
742                                 offset % row_size, nb);
743                 if (res != ERROR_OK)
744                         return res;
745
746                 /* We're done with the row contents */
747                 count -= nb;
748                 offset += nb;
749                 buffer += row_size;
750         }
751
752         /* There's at least one aligned row to write out. */
753         if (count >= row_size) {
754                 int nr = count / row_size + ((count % row_size) ? 1 : 0);
755                 unsigned int r = 0;
756
757                 for (unsigned int i = address / row_size;
758                                 (i < (address / row_size) + nr) && count > 0; i++) {
759                         address = (i * row_size) + bank->base;
760
761                         if (count >= row_size) {
762                                 res = samd_write_row(bank, address, buffer + (r * row_size));
763                                 /* Advance one row */
764                                 offset += row_size;
765                                 count -= row_size;
766                         } else {
767                                 res = samd_write_row_partial(bank, address,
768                                                 buffer + (r * row_size), 0, count);
769                                 /* We're done after this. */
770                                 offset += count;
771                                 count = 0;
772                         }
773
774                         r++;
775
776                         if (res != ERROR_OK)
777                                 return res;
778                 }
779         }
780
781         return ERROR_OK;
782 }
783
784 FLASH_BANK_COMMAND_HANDLER(samd_flash_bank_command)
785 {
786         struct samd_info *chip = samd_chips;
787
788         while (chip) {
789                 if (chip->target == bank->target)
790                         break;
791                 chip = chip->next;
792         }
793
794         if (!chip) {
795                 /* Create a new chip */
796                 chip = calloc(1, sizeof(*chip));
797                 if (!chip)
798                         return ERROR_FAIL;
799
800                 chip->target = bank->target;
801                 chip->probed = false;
802
803                 bank->driver_priv = chip;
804
805                 /* Insert it into the chips list (at head) */
806                 chip->next = samd_chips;
807                 samd_chips = chip;
808         }
809
810         if (bank->base != SAMD_FLASH) {
811                 LOG_ERROR("Address 0x%08" PRIx32 " invalid bank address (try 0x%08" PRIx32
812                                 "[at91samd series] )",
813                                 bank->base, SAMD_FLASH);
814                 return ERROR_FAIL;
815         }
816
817         return ERROR_OK;
818 }
819
820 COMMAND_HANDLER(samd_handle_info_command)
821 {
822         return ERROR_OK;
823 }
824
825 COMMAND_HANDLER(samd_handle_chip_erase_command)
826 {
827         struct target *target = get_current_target(CMD_CTX);
828
829         if (target) {
830                 /* Enable access to the DSU by disabling the write protect bit */
831                 target_write_u32(target, SAMD_PAC1, (1<<1));
832                 /* Tell the DSU to perform a full chip erase.  It takes about 240ms to
833                  * perform the erase. */
834                 target_write_u8(target, SAMD_DSU, (1<<4));
835
836                 command_print(CMD_CTX, "chip erased");
837         }
838
839         return ERROR_OK;
840 }
841
842 COMMAND_HANDLER(samd_handle_set_security_command)
843 {
844         int res = ERROR_OK;
845         struct target *target = get_current_target(CMD_CTX);
846
847         if (CMD_ARGC < 1 || (CMD_ARGC >= 1 && (strcmp(CMD_ARGV[0], "enable")))) {
848                 command_print(CMD_CTX, "supply the \"enable\" argument to proceed.");
849                 return ERROR_COMMAND_SYNTAX_ERROR;
850         }
851
852         if (target) {
853                 if (target->state != TARGET_HALTED) {
854                         LOG_ERROR("Target not halted");
855                         return ERROR_TARGET_NOT_HALTED;
856                 }
857
858                 res = samd_issue_nvmctrl_command(target, SAMD_NVM_CMD_SSB);
859
860                 /* Check (and clear) error conditions */
861                 if (res == ERROR_OK)
862                         command_print(CMD_CTX, "chip secured on next power-cycle");
863                 else
864                         command_print(CMD_CTX, "failed to secure chip");
865         }
866
867         return res;
868 }
869
870 COMMAND_HANDLER(samd_handle_eeprom_command)
871 {
872         int res = ERROR_OK;
873         struct target *target = get_current_target(CMD_CTX);
874
875         if (target) {
876                 if (target->state != TARGET_HALTED) {
877                         LOG_ERROR("Target not halted");
878                         return ERROR_TARGET_NOT_HALTED;
879                 }
880
881                 if (CMD_ARGC >= 1) {
882                         int val = atoi(CMD_ARGV[0]);
883                         uint32_t code;
884
885                         if (val == 0)
886                                 code = 7;
887                         else {
888                                 /* Try to match size in bytes with corresponding size code */
889                                 for (code = 0; code <= 6; code++) {
890                                         if (val == (2 << (13 - code)))
891                                                 break;
892                                 }
893
894                                 if (code > 6) {
895                                         command_print(CMD_CTX, "Invalid EEPROM size.  Please see "
896                                                         "datasheet for a list valid sizes.");
897                                         return ERROR_COMMAND_SYNTAX_ERROR;
898                                 }
899                         }
900
901                         res = samd_modify_user_row(target, code, 4, 6);
902                 } else {
903                         uint16_t val;
904                         res = target_read_u16(target, SAMD_USER_ROW, &val);
905                         if (res == ERROR_OK) {
906                                 uint32_t size = ((val >> 4) & 0x7); /* grab size code */
907
908                                 if (size == 0x7)
909                                         command_print(CMD_CTX, "EEPROM is disabled");
910                                 else {
911                                         /* Otherwise, 6 is 256B, 0 is 16KB */
912                                         command_print(CMD_CTX, "EEPROM size is %u bytes",
913                                                         (2 << (13 - size)));
914                                 }
915                         }
916                 }
917         }
918
919         return res;
920 }
921
922 COMMAND_HANDLER(samd_handle_bootloader_command)
923 {
924         int res = ERROR_OK;
925         struct target *target = get_current_target(CMD_CTX);
926
927         if (target) {
928                 if (target->state != TARGET_HALTED) {
929                         LOG_ERROR("Target not halted");
930                         return ERROR_TARGET_NOT_HALTED;
931                 }
932
933                 /* Retrieve the MCU's page size, in bytes. */
934                 uint32_t page_size;
935                 res = samd_get_flash_page_info(target, &page_size, NULL);
936                 if (res != ERROR_OK) {
937                         LOG_ERROR("Couldn't determine Flash page size");
938                         return res;
939                 }
940
941                 if (CMD_ARGC >= 1) {
942                         int val = atoi(CMD_ARGV[0]);
943                         uint32_t code;
944
945                         if (val == 0)
946                                 code = 7;
947                         else {
948                                 /* Try to match size in bytes with corresponding size code */
949                                 for (code = 0; code <= 6; code++) {
950                                         if ((unsigned int)val == (2UL << (8UL - code)) * page_size)
951                                                 break;
952                                 }
953
954                                 if (code > 6) {
955                                         command_print(CMD_CTX, "Invalid bootloader size.  Please "
956                                                         "see datasheet for a list valid sizes.");
957                                         return ERROR_COMMAND_SYNTAX_ERROR;
958                                 }
959
960                         }
961
962                         res = samd_modify_user_row(target, code, 0, 2);
963                 } else {
964                         uint16_t val;
965                         res = target_read_u16(target, SAMD_USER_ROW, &val);
966                         if (res == ERROR_OK) {
967                                 uint32_t size = (val & 0x7); /* grab size code */
968                                 uint32_t nb;
969
970                                 if (size == 0x7)
971                                         nb = 0;
972                                 else
973                                         nb = (2 << (8 - size)) * page_size;
974
975                                 /* There are 4 pages per row */
976                                 command_print(CMD_CTX, "Bootloader size is %u bytes (%u rows)",
977                                            nb, nb / (page_size * 4));
978                         }
979                 }
980         }
981
982         return res;
983 }
984
985 static const struct command_registration at91samd_exec_command_handlers[] = {
986         {
987                 .name = "info",
988                 .handler = samd_handle_info_command,
989                 .mode = COMMAND_EXEC,
990                 .help = "Print information about the current at91samd chip"
991                         "and its flash configuration.",
992         },
993         {
994                 .name = "chip-erase",
995                 .handler = samd_handle_chip_erase_command,
996                 .mode = COMMAND_EXEC,
997                 .help = "Erase the entire Flash by using the Chip"
998                         "Erase feature in the Device Service Unit (DSU).",
999         },
1000         {
1001                 .name = "set-security",
1002                 .handler = samd_handle_set_security_command,
1003                 .mode = COMMAND_EXEC,
1004                 .help = "Secure the chip's Flash by setting the Security Bit."
1005                         "This makes it impossible to read the Flash contents."
1006                         "The only way to undo this is to issue the chip-erase"
1007                         "command.",
1008         },
1009         {
1010                 .name = "eeprom",
1011                 .usage = "[size_in_bytes]",
1012                 .handler = samd_handle_eeprom_command,
1013                 .mode = COMMAND_EXEC,
1014                 .help = "Show or set the EEPROM size setting, stored in the User Row."
1015                         "Please see Table 20-3 of the SAMD20 datasheet for allowed values."
1016                         "Changes are stored immediately but take affect after the MCU is"
1017                         "reset.",
1018         },
1019         {
1020                 .name = "bootloader",
1021                 .usage = "[size_in_bytes]",
1022                 .handler = samd_handle_bootloader_command,
1023                 .mode = COMMAND_EXEC,
1024                 .help = "Show or set the bootloader size, stored in the User Row."
1025                         "Please see Table 20-2 of the SAMD20 datasheet for allowed values."
1026                         "Changes are stored immediately but take affect after the MCU is"
1027                         "reset.",
1028         },
1029         COMMAND_REGISTRATION_DONE
1030 };
1031
1032 static const struct command_registration at91samd_command_handlers[] = {
1033         {
1034                 .name = "at91samd",
1035                 .mode = COMMAND_ANY,
1036                 .help = "at91samd flash command group",
1037                 .usage = "",
1038                 .chain = at91samd_exec_command_handlers,
1039         },
1040         COMMAND_REGISTRATION_DONE
1041 };
1042
1043 struct flash_driver at91samd_flash = {
1044         .name = "at91samd",
1045         .commands = at91samd_command_handlers,
1046         .flash_bank_command = samd_flash_bank_command,
1047         .erase = samd_erase,
1048         .protect = samd_protect,
1049         .write = samd_write,
1050         .read = default_flash_read,
1051         .probe = samd_probe,
1052         .auto_probe = samd_probe,
1053         .erase_check = default_flash_blank_check,
1054         .protect_check = samd_protect_check,
1055 };