OpenOCD
pac55xx.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /*
4  * Copyright (C) 2019 by stfnbr <stfnbr@disroot.org>
5  */
6 
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10 
11 #include "imp.h"
12 #include <helper/bits.h>
13 #include <helper/time_support.h>
14 
15 #define PAC55XX_FLASH_BASE 0x00000000UL
16 
17 #define PAC55XX_PERIPH_BASE 0x40000000UL
18 #define PAC55XX_MEMCTL_BASE (PAC55XX_PERIPH_BASE + 0xD0000)
19 
20 #define PAC55XX_MEMCTL_FLASHSTATUS (PAC55XX_MEMCTL_BASE + 0x04) // status to show if flash is busy writing or erasing
21 #define PAC55XX_MEMCTL_FLASHLOCK (PAC55XX_MEMCTL_BASE + 0x08) // write a key to unlock the flash for write or erase
22 #define PAC55XX_MEMCTL_FLASHPAGE (PAC55XX_MEMCTL_BASE + 0x0C) // select a flash page
23 #define PAC55XX_MEMCTL_FLASHERASE (PAC55XX_MEMCTL_BASE + 0x20) // write a key to erase a flash page
24 
25 #define PAC55XX_MEMCTL_FLASHSTATUS_ERASEBUSY BIT(1) // erase in progress
26 #define PAC55XX_MEMCTL_FLASHSTATUS_WRITEBUSY BIT(0) // write in progress
27 
28 #define PAC55XX_MEMCTL_FLASHLOCK_ALLOWWRITEERASE 0x43DF140A
29 #define PAC55XX_MEMCTL_FLASHLOCK_LOCKED 0x0
30 #define PAC55XX_MEMCTL_FLASHERASE_ERASE 0x8C799CA7
31 
32 // Flash timeout values in milliseconds.
33 #define FLASH_ERASE_TIMEOUT_MS 20 // vendor specifies 2ms maximum for erase of a single page -> choose 20 to be safe
34 #define FLASH_WRITE_TIMEOUT_MS 20 // no upper limit specified - 20 seems to work fine
35 
42 static int pac55xx_wait_for_operation_to_finish(struct flash_bank *bank, unsigned int timeout_ms)
43 {
44  const int64_t start_time = timeval_ms();
45 
46  while (true) {
47  uint32_t status;
48 
49  // read status register
51  if (ret != ERROR_OK)
52  return ret;
53 
54  // check the busy-bits
57  return ERROR_OK;
58 
59  if ((timeval_ms() - start_time) > timeout_ms) {
60  LOG_ERROR("Timed out waiting for flash");
61  return ERROR_TIMEOUT_REACHED;
62  }
63 
64  keep_alive();
65  }
66 }
67 
68 int pac55xx_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
69 {
70  // target must be halted
71  if (bank->target->state != TARGET_HALTED) {
72  LOG_ERROR("Target must be halted to erase.");
74  }
75 
76  // Unlock flash
78  if (ret != ERROR_OK)
79  goto flash_lock;
80 
81  // loop through the pages to erase
82  for (unsigned int i = first; i < last; ++i) {
83  // define which page to erase
85  if (ret != ERROR_OK)
86  goto flash_lock;
87 
88  // start erase operation
90  if (ret != ERROR_OK)
91  goto flash_lock;
92 
93  // wait until operation is finished
95  if (ret != ERROR_OK)
96  goto flash_lock;
97  }
98 
99 flash_lock:
100  {
101  // lock the flash
103  if (ret == ERROR_OK)
104  ret = ret_lock_flash;
105  }
106 
107  return ret;
108 }
109 
110 int pac55xx_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
111 {
112  // target must be halted
113  if (bank->target->state != TARGET_HALTED) {
114  LOG_ERROR("Target must be halted to write.");
116  }
117 
118  // double check if start address is aligned to page size
119  // Writing must start at an address aligned to 16 bytes
120  assert(offset % 16 == 0);
121 
122  // double check if size is aligned to page size
123  // Size of write operation must always be aligned to 16 bytes
124  assert(count % 16 == 0);
125 
126  // unlock flash
128  if (ret != ERROR_OK)
129  goto flash_lock;
130 
131  for (uint32_t flash_address = PAC55XX_FLASH_BASE + offset;
132  flash_address < PAC55XX_FLASH_BASE + offset + count;
133  flash_address += 16, buffer += 16) {
134  // wait until flash is not busy anymore
136  if (ret != ERROR_OK)
137  goto flash_lock;
138 
139  // write 16 bytes to flash
140  ret = target_write_memory(bank->target, flash_address, 4, 4, buffer);
141  if (ret != ERROR_OK)
142  goto flash_lock;
143  }
144 
145  // wait until flash write operation finished
147  if (ret != ERROR_OK)
148  goto flash_lock;
149 
150 flash_lock:
151  {
152  // lock the flash
154  if (ret == ERROR_OK)
155  ret = ret_lock_flash;
156  }
157 
158  return ret;
159 }
160 
162 {
163  return ERROR_OK;
164 }
165 
166 FLASH_BANK_COMMAND_HANDLER(pac55xx_flash_bank_command)
167 {
168  uint32_t num_pages = 128;
169  uint32_t page_size = 0x400; // page size in bytes
170 
171  bank->base = PAC55XX_FLASH_BASE;
172  bank->size = num_pages * page_size;
173  bank->write_start_alignment = 16;
174  bank->write_end_alignment = 16;
175  bank->num_sectors = num_pages;
176 
177  bank->sectors = alloc_block_array(0, page_size, num_pages);
178  if (!bank->sectors)
179  return ERROR_FAIL;
180 
181  for (unsigned int i = 0; i < bank->num_sectors; i++)
182  bank->sectors[i].is_protected = 0;
183 
184  return ERROR_OK;
185 }
186 
187 const struct flash_driver pac55xx_flash = {
188  .name = "pac55xx",
189 
190  // const struct command_registration *commands;
191 
192  .flash_bank_command = pac55xx_flash_bank_command,
193  .erase = pac55xx_erase,
194  .write = pac55xx_write,
195  .probe = pac55xx_probe,
196  .read = default_flash_read,
197  .erase_check = default_flash_blank_check,
198  .auto_probe = pac55xx_probe,
199  .free_driver_priv = default_flash_free_driver_priv,
200 };
uint64_t buffer
Pointer to data buffer to send over SPI.
Definition: dw-spi-helper.h:0
uint32_t page_size
Page size.
Definition: dw-spi-helper.h:3
uint8_t bank
Definition: esirisc.c:135
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.
void keep_alive(void)
Definition: log.c:437
#define ERROR_FAIL
Definition: log.h:188
#define LOG_ERROR(expr ...)
Definition: log.h:147
#define ERROR_TIMEOUT_REACHED
Definition: log.h:191
#define ERROR_OK
Definition: log.h:182
#define PAC55XX_MEMCTL_FLASHSTATUS_WRITEBUSY
Definition: pac55xx.c:26
#define FLASH_WRITE_TIMEOUT_MS
Definition: pac55xx.c:34
int pac55xx_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
Definition: pac55xx.c:68
#define PAC55XX_MEMCTL_FLASHERASE
Definition: pac55xx.c:23
FLASH_BANK_COMMAND_HANDLER(pac55xx_flash_bank_command)
Definition: pac55xx.c:166
#define PAC55XX_MEMCTL_FLASHLOCK_LOCKED
Definition: pac55xx.c:29
#define PAC55XX_MEMCTL_FLASHLOCK_ALLOWWRITEERASE
Definition: pac55xx.c:28
#define PAC55XX_MEMCTL_FLASHSTATUS_ERASEBUSY
Definition: pac55xx.c:25
#define PAC55XX_MEMCTL_FLASHSTATUS
Definition: pac55xx.c:20
#define PAC55XX_FLASH_BASE
Definition: pac55xx.c:15
int pac55xx_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
Definition: pac55xx.c:110
#define PAC55XX_MEMCTL_FLASHERASE_ERASE
Definition: pac55xx.c:30
#define PAC55XX_MEMCTL_FLASHLOCK
Definition: pac55xx.c:21
int pac55xx_probe(struct flash_bank *bank)
Definition: pac55xx.c:161
const struct flash_driver pac55xx_flash
Definition: pac55xx.c:187
#define FLASH_ERASE_TIMEOUT_MS
Definition: pac55xx.c:33
#define PAC55XX_MEMCTL_FLASHPAGE
Definition: pac55xx.c:22
static int pac55xx_wait_for_operation_to_finish(struct flash_bank *bank, unsigned int timeout_ms)
Wait until the flash controller is not busy anymore.
Definition: pac55xx.c:42
Provides details of a flash bank, available either on-chip or through a major interface.
Definition: nor/core.h:75
Provides the implementation-independent structure that defines all of the callbacks required by OpenO...
Definition: nor/driver.h:39
const char * name
Gives a human-readable name of this flash driver, This field is used to select and initialize the dri...
Definition: nor/driver.h:44
int target_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
Write count items of size bytes to the memory of target at the address given.
Definition: target.c:1289
int target_write_u32(struct target *target, target_addr_t address, uint32_t value)
Definition: target.c:2676
int target_read_u32(struct target *target, target_addr_t address, uint32_t *value)
Definition: target.c:2602
#define ERROR_TARGET_NOT_HALTED
Definition: target.h:818
@ TARGET_HALTED
Definition: target.h:58
int64_t timeval_ms(void)
uint8_t status[4]
Definition: vdebug.c:17
uint8_t offset[4]
Definition: vdebug.c:9
uint8_t count[4]
Definition: vdebug.c:22