42 #define QN908X_FLASH_BASE 0x01000000
44 #define QN908X_FLASH_PAGE_SIZE 2048
45 #define QN908X_FLASH_PAGES_PER_BLOCK 128
46 #define QN908X_FLASH_MAX_BLOCKS 2
47 #define QN908X_FLASH_BLOCK_SIZE \
48 (QN908X_FLASH_PAGES_PER_BLOCK * QN908X_FLASH_PAGE_SIZE)
49 #define QN908X_FLASH_IRQ_VECTOR_CHECKSUM_POS 0x1c
50 #define QN908X_FLASH_IRQ_VECTOR_CHECKSUM_SIZE 4
51 #define QN908X_FLASH_IRQ_VECTOR_CHECKSUM_END \
52 (QN908X_FLASH_IRQ_VECTOR_CHECKSUM_POS + QN908X_FLASH_IRQ_VECTOR_CHECKSUM_SIZE)
56 #define QN908X_INFO_PAGE_BASE 0x210b0000u
57 #define QN908X_INFO_PAGE_CRC32 (QN908X_INFO_PAGE_BASE + 0x700)
58 #define QN908X_INFO_PAGE_CRC_START (QN908X_INFO_PAGE_BASE + 0x704)
59 #define QN908X_INFO_PAGE_BOOTLOADER_VER (QN908X_INFO_PAGE_BASE + 0x704)
60 #define QN908X_INFO_PAGE_FLASH_SIZE (QN908X_INFO_PAGE_BASE + 0x708)
61 #define QN908X_INFO_PAGE_BLUETOOTH_ADDR (QN908X_INFO_PAGE_BASE + 0x7fa)
62 #define QN908X_INFO_PAGE_CRC_END (QN908X_INFO_PAGE_BASE + 0x800)
75 #define QN908X_FMC_BASE 0x40081000u
76 #define QN908X_FMC_INI_RD_EN (QN908X_FMC_BASE + 0x00)
77 #define QN908X_FMC_ERASE_CTRL (QN908X_FMC_BASE + 0x04)
78 #define QN908X_FMC_ERASE_TIME (QN908X_FMC_BASE + 0x08)
79 #define QN908X_FMC_TIME_CTRL (QN908X_FMC_BASE + 0x0c)
80 #define QN908X_FMC_SMART_CTRL (QN908X_FMC_BASE + 0x10)
81 #define QN908X_FMC_INT_STAT (QN908X_FMC_BASE + 0x18)
82 #define QN908X_FMC_LOCK_STAT_0 (QN908X_FMC_BASE + 0x20)
83 #define QN908X_FMC_LOCK_STAT_1 (QN908X_FMC_BASE + 0x24)
84 #define QN908X_FMC_LOCK_STAT_2 (QN908X_FMC_BASE + 0x28)
85 #define QN908X_FMC_LOCK_STAT_3 (QN908X_FMC_BASE + 0x2c)
86 #define QN908X_FMC_LOCK_STAT_4 (QN908X_FMC_BASE + 0x30)
87 #define QN908X_FMC_LOCK_STAT_5 (QN908X_FMC_BASE + 0x34)
88 #define QN908X_FMC_LOCK_STAT_6 (QN908X_FMC_BASE + 0x38)
89 #define QN908X_FMC_LOCK_STAT_7 (QN908X_FMC_BASE + 0x3c)
90 #define QN908X_FMC_LOCK_STAT_8 (QN908X_FMC_BASE + 0x40)
91 #define QN908X_FMC_STATUS1 (QN908X_FMC_BASE + 0x48)
92 #define QN908X_FMC_DEBUG_PASSWORD (QN908X_FMC_BASE + 0xa8)
93 #define QN908X_FMC_ERASE_PASSWORD (QN908X_FMC_BASE + 0xac)
95 #define QN908X_FMC_INI_RD_EN_INI_RD_EN_MASK BIT(0)
97 #define QN908X_FMC_STATUS1_FSH_ERA_BUSY_L_MASK BIT(9)
98 #define QN908X_FMC_STATUS1_FSH_WR_BUSY_L_MASK BIT(10)
99 #define QN908X_FMC_STATUS1_FSH_ERA_BUSY_H_MASK BIT(12)
100 #define QN908X_FMC_STATUS1_FSH_WR_BUSY_H_MASK BIT(13)
101 #define QN908X_FMC_STATUS1_INI_RD_DONE_MASK BIT(15)
102 #define QN908X_FMC_STATUS1_FSH_STA_MASK BIT(26)
104 #define QN908X_FMC_ERASE_CTRL_PAGE_IDXL_SHIFT 0
105 #define QN908X_FMC_ERASE_CTRL_PAGE_IDXH_SHIFT 8
106 #define QN908X_FMC_ERASE_CTRL_HALF_ERASEL_EN_SHIFT 28
107 #define QN908X_FMC_ERASE_CTRL_HALF_ERASEH_EN_SHIFT 29
108 #define QN908X_FMC_ERASE_CTRL_PAGE_ERASEL_EN_SHIFT 30
109 #define QN908X_FMC_ERASE_CTRL_PAGE_ERASEH_EN_SHIFT 31
111 #define QN908X_FMC_INT_STAT_AHBL_INT_MASK BIT(0)
112 #define QN908X_FMC_INT_STAT_LOCKL_INT_MASK BIT(1)
113 #define QN908X_FMC_INT_STAT_ERASEL_INT_MASK BIT(2)
114 #define QN908X_FMC_INT_STAT_WRITEL_INT_MASK BIT(3)
115 #define QN908X_FMC_INT_STAT_WR_BUFL_INT_MASK BIT(4)
116 #define QN908X_FMC_INT_STAT_WRITE_FAIL_L_INT_MASK BIT(5)
117 #define QN908X_FMC_INT_STAT_ERASE_FAIL_L_INT_MASK BIT(6)
118 #define QN908X_FMC_INT_STAT_AHBH_INT_MASK BIT(8)
119 #define QN908X_FMC_INT_STAT_LOCKH_INT_MASK BIT(9)
120 #define QN908X_FMC_INT_STAT_ERASEH_INT_MASK BIT(10)
121 #define QN908X_FMC_INT_STAT_WRITEH_INT_MASK BIT(11)
122 #define QN908X_FMC_INT_STAT_WR_BUFH_INT_MASK BIT(12)
123 #define QN908X_FMC_INT_STAT_WRITE_FAIL_H_INT_MASK BIT(13)
124 #define QN908X_FMC_INT_STAT_ERASE_FAIL_H_INT_MASK BIT(14)
126 #define QN908X_FMC_SMART_CTRL_PRGML_EN_MASK BIT(0)
127 #define QN908X_FMC_SMART_CTRL_PRGMH_EN_MASK BIT(1)
128 #define QN908X_FMC_SMART_CTRL_SMART_WRITEL_EN_MASK BIT(2)
129 #define QN908X_FMC_SMART_CTRL_SMART_WRITEH_EN_MASK BIT(3)
130 #define QN908X_FMC_SMART_CTRL_SMART_ERASEL_EN_MASK BIT(4)
131 #define QN908X_FMC_SMART_CTRL_SMART_ERASEH_EN_MASK BIT(5)
132 #define QN908X_FMC_SMART_CTRL_MAX_WRITE_MASK 0xf00u
133 #define QN908X_FMC_SMART_CTRL_MAX_WRITE_SHIFT 8u
134 #define QN908X_FMC_SMART_CTRL_MAX_WRITE(x) \
135 (((uint32_t)(((uint32_t)(x)) << QN908X_FMC_SMART_CTRL_MAX_WRITE_SHIFT)) \
136 & QN908X_FMC_SMART_CTRL_MAX_WRITE_MASK)
137 #define QN908X_FMC_SMART_CTRL_MAX_ERASE_MASK 0x3f000u
138 #define QN908X_FMC_SMART_CTRL_MAX_ERASE_SHIFT 12u
139 #define QN908X_FMC_SMART_CTRL_MAX_ERASE(x) \
140 (((uint32_t)(((uint32_t)(x)) << QN908X_FMC_SMART_CTRL_MAX_ERASE_SHIFT)) \
141 & QN908X_FMC_SMART_CTRL_MAX_ERASE_MASK)
143 #define QN908X_FMC_SMART_CTRL_MAX_ERASE_RETRIES 9
144 #define QN908X_FMC_SMART_CTRL_MAX_WRITE_RETRIES 9
146 #define QN908X_FMC_TIME_CTRL_PRGM_CYCLE_MASK 0xfffu
147 #define QN908X_FMC_TIME_CTRL_PRGM_CYCLE_SHIFT 0u
148 #define QN908X_FMC_TIME_CTRL_PRGM_CYCLE(x) \
149 (((uint32_t)(((uint32_t)(x)) << QN908X_FMC_TIME_CTRL_PRGM_CYCLE_SHIFT)) \
150 & QN908X_FMC_TIME_CTRL_PRGM_CYCLE_MASK)
151 #define QN908X_FMC_TIME_CTRL_TIME_BASE_MASK 0xff000u
152 #define QN908X_FMC_TIME_CTRL_TIME_BASE_SHIFT 12u
153 #define QN908X_FMC_TIME_CTRL_TIME_BASE(x) \
154 (((uint32_t)(((uint32_t)(x)) << QN908X_FMC_TIME_CTRL_TIME_BASE_SHIFT)) \
155 & QN908X_FMC_TIME_CTRL_TIME_BASE_MASK)
157 #define QN908X_FMC_LOCK_STAT_8_MASS_ERASE_LOCK_EN BIT(0)
158 #define QN908X_FMC_LOCK_STAT_8_FSH_PROTECT_EN BIT(1)
159 #define QN908X_FMC_LOCK_STAT_8_MEM_PROTECT_EN BIT(2)
160 #define QN908X_FMC_LOCK_STAT_8_PROTECT_ANY (BIT(1) | BIT(2))
163 #define QN908X_FLASH_LOCK_ADDR (QN908X_FLASH_BASE + 0x7f820)
165 #define QN908X_FLASH_LOCK_ENABLE_MASS_ERASE BIT(0)
167 #define QN908X_FLASH_LOCK_ENABLE_FLASH_PROTECTION BIT(1)
169 #define QN908X_FLASH_LOCK_ENABLE_MEMORY_PROTECTION BIT(2)
182 #define QN908X_SYSCON_BASE 0x40000000u
183 #define QN908X_SYSCON_CLK_EN (QN908X_SYSCON_BASE + 0x00cu)
184 #define QN908X_SYSCON_CLK_CTRL (QN908X_SYSCON_BASE + 0x010u)
185 #define QN908X_SYSCON_CHIP_ID (QN908X_SYSCON_BASE + 0x108u)
186 #define QN908X_SYSCON_XTAL_CTRL (QN908X_SYSCON_BASE + 0x180u)
189 #define QN908X_SYSCON_CLK_EN_CLK_DP_EN_MASK BIT(21)
191 #define SYSCON_XTAL_CTRL_XTAL_DIV_MASK BIT(31)
193 #define SYSCON_CLK_CTRL_AHB_DIV_MASK 0x1FFF0u
194 #define SYSCON_CLK_CTRL_AHB_DIV_SHIFT 4u
195 #define SYSCON_CLK_CTRL_CLK_XTAL_SEL_MASK BIT(19)
196 #define SYSCON_CLK_CTRL_CLK_OSC32M_DIV_MASK BIT(20)
197 #define SYSCON_CLK_CTRL_SYS_CLK_SEL_MASK 0xC0000000u
198 #define SYSCON_CLK_CTRL_SYS_CLK_SEL_SHIFT 30u
200 #define CLOCK_16MHZ 16000000u
201 #define CLOCK_32MHZ 32000000u
202 #define CLOCK_32KHZ 32000u
205 #define QN908X_WDT_BASE 0x40001000u
206 #define QN908X_WDT_CTRL (QN908X_WDT_BASE + 0x08u)
207 #define QN908X_WDT_LOCK (QN908X_WDT_BASE + 0x20u)
226 #define QN908X_DEFAULT_TIMEOUT_MS 500
237 uint32_t
mask, uint32_t value)
239 uint32_t orig_value = 0;
242 if (
mask != 0xffffffff) {
247 ": %d",
reg, retval);
251 new_value = (orig_value & ~
mask) | (value &
mask);
255 PRIx32
": %d",
reg, new_value, retval);
258 if (
mask == 0xffffffff) {
260 PRIx32
"",
reg, new_value);
263 " -> 0x%.08" PRIx32,
reg, orig_value, new_value);
287 for (
int i = 0; i <= 8; i++) {
291 LOG_DEBUG(
"LOCK_STAT_%d = 0x%08" PRIx32, i, lock_stat);
307 LOG_DEBUG(
"Clock clk_sel=0x%08" PRIu32, clk_sel);
310 uint32_t core_freq = 0;
336 uint32_t ahb_freq = core_freq / (ahb_div + 1);
338 LOG_DEBUG(
"Core freq: %" PRIu32
" Hz | AHB freq: %" PRIu32
" Hz",
339 core_freq, ahb_freq);
356 if (CMD_ARGC < 6 || CMD_ARGC > 7)
361 " is an invalid bank address (try 0x%08" PRIx32
")",
371 bank->driver_priv = qn908x_info;
379 if (strcmp(
CMD_ARGV[6],
"calc_checksum")) {
409 LOG_DEBUG(
"Flash protection = 0x%02" PRIx8,
441 for (
unsigned int block = 0; block <= 1; block++) {
442 unsigned int shift = (block) ? 8 : 0;
444 LOG_ERROR(
"AHB error on block %u", block);
449 LOG_ERROR(
"Locked page being accessed error on block %u", block);
454 LOG_ERROR(
"Smart write on block %u failed", block);
460 LOG_ERROR(
"Smart erase on block %u failed", block);
478 LOG_ERROR(
"Timeout waiting to be idle.");
539 for (
unsigned int i = first; i <= last; i++) {
540 if (i >=
bank->num_sectors)
547 LOG_DEBUG(
"Erasing page %" PRIu32
" of block %" PRIu32,
548 page_idx, block_idx);
552 uint32_t ctrl_page_idx_shift = block_idx ?
555 uint32_t ctrl_erase_en_shift = block_idx ?
560 BIT(ctrl_erase_en_shift) | (page_idx << ctrl_page_idx_shift));
595 bool needs_update =
false;
596 for (
unsigned int i = first; i < last; i++) {
597 if (set != (((qn908x_info->
page_lock.
bits[i / 8] >> (i % 8)) & 1) ^ 1))
605 LOG_WARNING(
"SWD flash/RAM access disabled in the Flash lock and "
606 "protect descriptor. You might need to issue a mass_erase to "
607 "regain SWD access to this chip after reboot.");
628 LOG_ERROR(
"Unprotecting the last page is not supported. Issue a "
629 "\"qn908x mass_erase\" command to erase the whole flash, "
630 "including the last page and its protection.");
634 for (
unsigned int i = first / 8; i < (last + 7) / 8; i++) {
638 uint8_t first_mask = (first <= i * 8)
639 ? 0xff : 0xff ^ ((1u << (first - i * 8)) - 1);
642 uint8_t last_mask = (i * 8 + 8 <= last)
643 ? 0xff : ((1u << (last - i * 8)) - 1);
645 uint8_t
mask = first_mask & last_mask;
646 LOG_DEBUG(
"protect set=%d bits[%d] with mask=0x%02x", set, i,
mask);
665 for (
unsigned int i = first; i < last; i++)
666 bank->sectors[i].is_protected = set;
686 uint32_t checksum = 0;
688 for (
int i = 0; i < 7; i++)
690 checksum = 0 - checksum;
691 LOG_DEBUG(
"computed image checksum: 0x%8.8" PRIx32, checksum);
693 if (checksum != stored_checksum) {
694 LOG_WARNING(
"Image vector table checksum mismatch: expected 0x%08"
695 PRIx32
" but found 0x%08" PRIx32,
696 checksum, stored_checksum);
698 LOG_WARNING(
"This device will not boot, use calc_checksum in "
701 LOG_WARNING(
"Updating checksum, verification will fail.");
707 if (offset <= 0x20 && offset + count >= 0x24) {
710 for (
int i = 10; i <= 18; i += 2) {
711 uint32_t field = (crp >> i) & 3;
712 if (field == 0 || field == 3) {
713 LOG_DEBUG(
"Code Read Protection = 0x%08" PRIx32, crp);
714 LOG_ERROR(
"The Code Read Protection (CRP) field at bit %d is "
715 "invalid (%" PRIu32
"). An invalid value could make "
716 "the flash inaccessible.", i, field);
721 uint32_t swd_allowed = (crp >> 18) & 3;
722 if (swd_allowed != 2) {
723 LOG_WARNING(
"The Code Read Protection (CRP) in this image "
724 "(0x%08" PRIx32
") is disabling the SWD access, which is "
725 "currently used by OpenOCD to flash this device. After "
726 "reboot, this device will not be accessible to OpenOCD "
729 LOG_ERROR(
"Disabling SWD is not allowed, run "
730 "\"qn908x allow_brick\" before if you really want to "
731 "disable SWD. You won't be able to access this chip "
732 "anymore from OpenOCD.");
758 uint32_t chunk_len = next_offset -
offset;
759 if (chunk_len >
count)
815 *is_protected =
false;
817 *is_protected =
true;
838 sizeof(uint32_t),
sizeof(info_page) /
sizeof(uint32_t),
843 const uint32_t crc_seed = 0xffffffff;
848 info_page,
sizeof(info_page));
849 computed_crc ^= crc_seed;
855 if (computed_crc != read_crc) {
856 uint32_t info_page_or = 0;
857 for (
unsigned int i = 0; i <
sizeof(info_page); i++)
858 info_page_or |= info_page[i];
864 if (info_page_or == 0 && is_protected) {
865 LOG_ERROR(
"The flash or memory in this chip is protected and "
866 "cannot be accessed from the SWD interface. However, a "
867 "\"qn908x mass_erase\" can erase the device and lift this "
872 LOG_ERROR(
"Flash information page CRC32 mismatch, found 0x%08"
873 PRIx32
" but computed 0x%08" PRIx32
". Flash size unknown",
874 read_crc, computed_crc);
881 switch (flash_size_fld) {
889 LOG_ERROR(
"Unknown Flash size field: 0x%08" PRIx32,
895 bank->write_start_alignment = 4;
896 bank->write_end_alignment = 4;
910 LOG_INFO(
"Detected flash size: %d KiB",
bank->size / 1024);
936 bank->sectors[i].is_protected =
945 uint32_t bootloader_version;
947 uint8_t bluetooth[6];
957 &bootloader_version);
964 1,
sizeof(bluetooth), bluetooth);
973 "%02" PRIx8
":%02" PRIx8
":%02" PRIx8
974 ":%02" PRIx8
":%02" PRIx8
":%02" PRIx8,
975 bluetooth[0], bluetooth[1], bluetooth[2],
976 bluetooth[3], bluetooth[4], bluetooth[5]);
1004 LOG_WARNING(
"Flashing images that disable SWD in qn908x is now allowed.");
1040 bool keep_lock =
false;
1044 if (strcmp(
"keep_lock",
CMD_ARGV[0]))
1060 uint32_t lock_stat_8;
1062 LOG_DEBUG(
"LOCK_STAT_8 before erasing: 0x%" PRIx32, lock_stat_8);
1066 LOG_INFO(
"mass_erase disabled by Flash lock and protection, forcing "
1083 LOG_DEBUG(
"Erasing both blocks with command 0x%" PRIx32, erase_cmd);
1147 .
name =
"allow_brick",
1148 .handler = qn908x_handle_allow_brick_command,
1150 .help =
"Allow writing images that disable SWD access in their "
1151 "Code Read Protection (CRP) word. Warning: This can make your "
1152 "chip inaccessible from OpenOCD or any other SWD debugger.",
1156 .name =
"disable_wdog",
1157 .handler = qn908x_handle_disable_wdog_command,
1159 .help =
"Disabled the watchdog (WDT).",
1163 .name =
"mass_erase",
1164 .handler = qn908x_handle_mass_erase_command,
1166 .help =
"Erase the whole flash chip.",
1167 .usage =
"[keep_lock]",
1176 .help =
"qn908x flash controller commands",
1186 .flash_bank_command = qn908x_flash_bank_command,
Support functions to access arbitrary bits in a byte array.
static uint32_t buf_get_u32(const uint8_t *_buffer, unsigned int first, unsigned int num)
Retrieves num bits from _buffer, starting at the first bit, returning the bits in a 32-bit word.
void command_print_sameline(struct command_invocation *cmd, const char *format,...)
void command_print(struct command_invocation *cmd, const char *format,...)
#define CMD
Use this macro to access the command being handled, rather than accessing the variable directly.
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
#define ERROR_COMMAND_SYNTAX_ERROR
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
#define CMD_CTX
Use this macro to access the context of the command being handled, rather than accessing the variable...
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
#define ERROR_COMMAND_ARGUMENT_INVALID
uint32_t crc32_le(uint32_t poly, uint32_t seed, const void *_data, size_t data_len)
Calculate the CRC32 value of the given data.
A generic CRC32 implementation.
#define CRC32_POLY_LE
CRC32 polynomial commonly used for little endian CRC32.
#define ERROR_FLASH_SECTOR_INVALID
#define ERROR_FLASH_BANK_NOT_PROBED
struct flash_sector * alloc_block_array(uint32_t offset, uint32_t size, unsigned int num_blocks)
Allocate and fill an array of sectors or protection blocks.
int default_flash_blank_check(struct flash_bank *bank)
Provides default erased-bank check handling.
int default_flash_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
Provides default read implementation for flash memory.
void default_flash_free_driver_priv(struct flash_bank *bank)
Deallocates bank->driver_priv.
int get_flash_bank_by_addr(struct target *target, target_addr_t addr, bool check, struct flash_bank **result_bank)
Returns the flash bank located at a specified address.
#define LOG_WARNING(expr ...)
#define LOG_ERROR(expr ...)
#define ERROR_TIMEOUT_REACHED
#define LOG_INFO(expr ...)
#define LOG_DEBUG(expr ...)
#define QN908X_FMC_TIME_CTRL_PRGM_CYCLE(x)
#define QN908X_FMC_TIME_CTRL_TIME_BASE(x)
static int qn908x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
#define QN908X_INFO_PAGE_CRC32
static int qn908x_setup_erase(struct target *target)
#define QN908X_FMC_LOCK_STAT_8
#define QN908X_FMC_SMART_CTRL_MAX_ERASE_RETRIES
#define QN908X_FMC_TIME_CTRL
#define QN908X_FMC_SMART_CTRL_MAX_ERASE(x)
static int qn908x_auto_probe(struct flash_bank *bank)
#define QN908X_INFO_PAGE_FLASH_SIZE
static int qn908x_init_flash(struct target *target)
#define QN908X_FMC_ERASE_CTRL_PAGE_ERASEH_EN_SHIFT
static int qn908x_status_check(struct target *target)
static int qn908x_get_info(struct flash_bank *bank, struct command_invocation *cmd)
#define QN908X_FMC_STATUS1_INI_RD_DONE_MASK
#define QN908X_FMC_ERASE_CTRL_HALF_ERASEH_EN_SHIFT
#define QN908X_FMC_STATUS1
#define QN908X_FMC_SMART_CTRL_SMART_WRITEH_EN_MASK
#define QN908X_INFO_PAGE_BLUETOOTH_ADDR
const struct flash_driver qn908x_flash
#define QN908X_FLASH_IRQ_VECTOR_CHECKSUM_POS
#define QN908X_FMC_INT_STAT_WRITE_FAIL_L_INT_MASK
#define QN908X_FMC_INT_STAT_LOCKL_INT_MASK
#define SYSCON_CLK_CTRL_CLK_XTAL_SEL_MASK
static int qn908x_protect_check(struct flash_bank *bank)
#define SYSCON_XTAL_CTRL_XTAL_DIV_MASK
#define QN908X_FMC_ERASE_TIME
#define QN908X_FMC_SMART_CTRL_MAX_WRITE(x)
#define QN908X_INFO_PAGE_CRC_END
#define QN908X_FLASH_IRQ_VECTOR_CHECKSUM_END
static int qn908x_wait_for_idle(struct target *target, int64_t timeout_ms)
#define QN908X_FMC_INT_STAT
#define QN908X_FMC_INI_RD_EN_INI_RD_EN_MASK
static const struct command_registration qn908x_exec_command_handlers[]
#define QN908X_FMC_SMART_CTRL
#define QN908X_FMC_STATUS1_FSH_ERA_BUSY_H_MASK
#define QN908X_FLASH_BLOCK_SIZE
static int qn908x_probe(struct flash_bank *bank)
static int is_flash_protected(struct flash_bank *bank, bool *is_protected)
#define QN908X_FMC_SMART_CTRL_PRGMH_EN_MASK
#define QN908X_FMC_SMART_CTRL_MAX_WRITE_RETRIES
static const struct command_registration qn908x_command_handlers[]
#define QN908X_FLASH_LOCK_ENABLE_MASS_ERASE
#define QN908X_FMC_SMART_CTRL_PRGML_EN_MASK
#define QN908X_FLASH_MAX_BLOCKS
#define QN908X_FMC_INT_STAT_ERASE_FAIL_H_INT_MASK
#define QN908X_SYSCON_CLK_EN_CLK_DP_EN_MASK
#define QN908X_SYSCON_CLK_CTRL
qn908x_info_page_flash_size
#define QN908X_SYSCON_CHIP_ID
#define QN908X_FMC_STATUS1_FSH_WR_BUSY_H_MASK
#define QN908X_FMC_STATUS1_FSH_WR_BUSY_L_MASK
#define QN908X_FMC_STATUS1_FSH_STA_MASK
#define SYSCON_CLK_CTRL_AHB_DIV_SHIFT
#define QN908X_FLASH_LOCK_ADDR
#define SYSCON_CLK_CTRL_AHB_DIV_MASK
COMMAND_HANDLER(qn908x_handle_allow_brick_command)
#define QN908X_FMC_DEBUG_PASSWORD
#define QN908X_FLASH_BASE
#define QN908X_FMC_INT_STAT_AHBL_INT_MASK
#define QN908X_FMC_LOCK_STAT_8_MASS_ERASE_LOCK_EN
#define QN908X_FMC_ERASE_CTRL
#define SYSCON_CLK_CTRL_SYS_CLK_SEL_MASK
static int qn908x_busy_check(struct target *target)
#define SYSCON_CLK_CTRL_SYS_CLK_SEL_SHIFT
#define SYSCON_CLK_CTRL_CLK_OSC32M_DIV_MASK
struct qn908x_flash_bank __attribute__
#define QN908X_FMC_SMART_CTRL_SMART_ERASEL_EN_MASK
#define QN908X_FMC_SMART_CTRL_SMART_WRITEL_EN_MASK
#define QN908X_FMC_SMART_CTRL_SMART_ERASEH_EN_MASK
#define QN908X_INFO_PAGE_CRC_START
static int qn908x_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last)
#define QN908X_FMC_STATUS1_FSH_ERA_BUSY_L_MASK
#define QN908X_FLASH_PAGES_PER_BLOCK
static int qn908x_read_page_lock(struct flash_bank *bank)
static int qn908x_load_lock_stat(struct target *target)
#define QN908X_INFO_PAGE_BOOTLOADER_VER
#define QN908X_FLASH_PAGE_SIZE
#define QN908X_SYSCON_CLK_EN
#define QN908X_FMC_LOCK_STAT_0
static int qn908x_update_reg(struct target *target, target_addr_t reg, uint32_t mask, uint32_t value)
#define QN908X_FMC_ERASE_CTRL_PAGE_IDXL_SHIFT
FLASH_BANK_COMMAND_HANDLER(qn908x_flash_bank_command)
#define QN908X_FMC_ERASE_CTRL_HALF_ERASEL_EN_SHIFT
#define QN908X_FMC_INI_RD_EN
#define QN908X_FMC_LOCK_STAT_8_PROTECT_ANY
#define QN908X_FMC_ERASE_CTRL_PAGE_ERASEL_EN_SHIFT
#define QN908X_FMC_ERASE_CTRL_PAGE_IDXH_SHIFT
#define QN908X_FMC_INT_STAT_ERASE_FAIL_L_INT_MASK
#define QN908X_SYSCON_XTAL_CTRL
#define QN908X_DEFAULT_TIMEOUT_MS
static int qn908x_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
target_addr_t addr
Start address to search for the control block.
When run_command is called, a new instance will be created on the stack, filled with the proper value...
Provides details of a flash bank, available either on-chip or through a major interface.
Provides the implementation-independent structure that defines all of the callbacks required by OpenO...
const char * name
Gives a human-readable name of this flash driver, This field is used to select and initialize the dri...
struct qn908x_flash_page_lock page_lock
unsigned int user_bank_size
uint8_t bits[QN908X_FLASH_MAX_BLOCKS *QN908X_FLASH_PAGES_PER_BLOCK/8]
int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
int target_write_u32(struct target *target, target_addr_t address, uint32_t value)
int target_read_u32(struct target *target, target_addr_t address, uint32_t *value)
int target_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
Read count items of size bytes from the memory of target at the address given.
struct target * get_current_target(struct command_context *cmd_ctx)
uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer)
#define ERROR_TARGET_NOT_HALTED