/***************************************************************************
* Copyright (C) 2013 by Andrey Yurovsky *
* Andrey Yurovsky <yurovsky@gmail.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "imp.h"
#include "helper/binarybuffer.h"
#include <target/cortex_m.h>
#define SAMD_NUM_PROT_BLOCKS 16
#define SAMD_PAGE_SIZE_MAX 1024
#define SAMD_FLASH ((uint32_t)0x00000000) /* physical Flash memory */
#define SAMD_USER_ROW ((uint32_t)0x00804000) /* User Row of Flash */
#define SAMD_PAC1 0x41000000 /* Peripheral Access Control 1 */
#define SAMD_DSU 0x41002000 /* Device Service Unit */
#define SAMD_NVMCTRL 0x41004000 /* Non-volatile memory controller */
#define SAMD_DSU_STATUSA 1 /* DSU status register */
#define SAMD_DSU_DID 0x18 /* Device ID register */
#define SAMD_DSU_CTRL_EXT 0x100 /* CTRL register, external access */
#define SAMD_NVMCTRL_CTRLA 0x00 /* NVM control A register */
#define SAMD_NVMCTRL_CTRLB 0x04 /* NVM control B register */
#define SAMD_NVMCTRL_PARAM 0x08 /* NVM parameters register */
#define SAMD_NVMCTRL_INTFLAG 0x18 /* NVM Interupt Flag Status & Clear */
#define SAMD_NVMCTRL_STATUS 0x18 /* NVM status register */
#define SAMD_NVMCTRL_ADDR 0x1C /* NVM address register */
#define SAMD_NVMCTRL_LOCK 0x20 /* NVM Lock section register */
#define SAMD_CMDEX_KEY 0xA5UL
#define SAMD_NVM_CMD(n) ((SAMD_CMDEX_KEY << 8) | (n & 0x7F))
/* NVMCTRL commands. See Table 20-4 in 42129F–SAM–10/2013 */
#define SAMD_NVM_CMD_ER 0x02 /* Erase Row */
#define SAMD_NVM_CMD_WP 0x04 /* Write Page */
#define SAMD_NVM_CMD_EAR 0x05 /* Erase Auxilary Row */
#define SAMD_NVM_CMD_WAP 0x06 /* Write Auxilary Page */
#define SAMD_NVM_CMD_LR 0x40 /* Lock Region */
#define SAMD_NVM_CMD_UR 0x41 /* Unlock Region */
#define SAMD_NVM_CMD_SPRM 0x42 /* Set Power Reduction Mode */
#define SAMD_NVM_CMD_CPRM 0x43 /* Clear Power Reduction Mode */
#define SAMD_NVM_CMD_PBC 0x44 /* Page Buffer Clear */
#define SAMD_NVM_CMD_SSB 0x45 /* Set Security Bit */
#define SAMD_NVM_CMD_INVALL 0x46 /* Invalidate all caches */
/* NVMCTRL bits */
#define SAMD_NVM_CTRLB_MANW 0x80
/* Known identifiers */
#define SAMD_PROCESSOR_M0 0x01
#define SAMD_FAMILY_D 0x00
#define SAMD_FAMILY_L 0x01
#define SAMD_FAMILY_C 0x02
#define SAMD_SERIES_20 0x00
#define SAMD_SERIES_21 0x01
#define SAMD_SERIES_22 0x02
#define SAMD_SERIES_10 0x02
#define SAMD_SERIES_11 0x03
#define SAMD_SERIES_09 0x04
/* Device ID macros */
#define SAMD_GET_PROCESSOR(id) (id >> 28)
#define SAMD_GET_FAMILY(id) (((id >> 23) & 0x1F))
#define SAMD_GET_SERIES(id) (((id >> 16) & 0x3F))
#define SAMD_GET_DEVSEL(id) (id & 0xFF)
/* Bits to mask out lockbits in user row */
#define NVMUSERROW_LOCKBIT_MASK ((uint64_t)0x0000FFFFFFFFFFFF)
struct samd_part {
uint8_t id;
const char *name;
uint32_t flash_kb;
uint32_t ram_kb;
};
/* Known SAMD09 parts. DID reset values missing in RM, see
* https://github.com/avrxml/asf/blob/master/sam0/utils/cmsis/samd09/include/ */
static const struct samd_part samd09_parts[] = {
{ 0x0, "SAMD09D14A", 16, 4 },
{ 0x7, "SAMD09C13A", 8, 4 },
};
/* Known SAMD10 parts */
static const struct samd_part samd10_parts[] = {
{ 0x0, "SAMD10D14AMU", 16, 4 },
{ 0x1, "SAMD10D13AMU", 8, 4 },
{ 0x2, "SAMD10D12AMU", 4, 4 },
{ 0x3, "SAMD10D14ASU", 16, 4 },
{ 0x4, "SAMD10D13ASU", 8, 4 },
{ 0x5, "SAMD10D12ASU", 4, 4 },
{ 0x6, "SAMD10C14A", 16, 4