[374] | 1 | /* mbed Microcontroller Library
|
---|
| 2 | * Copyright (c) 2018 ARM Limited
|
---|
| 3 | *
|
---|
| 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
---|
| 5 | * you may not use this file except in compliance with the License.
|
---|
| 6 | * You may obtain a copy of the License at
|
---|
| 7 | *
|
---|
| 8 | * http://www.apache.org/licenses/LICENSE-2.0
|
---|
| 9 | *
|
---|
| 10 | * Unless required by applicable law or agreed to in writing, software
|
---|
| 11 | * distributed under the License is distributed on an "AS IS" BASIS,
|
---|
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
---|
| 13 | * See the License for the specific language governing permissions and
|
---|
| 14 | * limitations under the License.
|
---|
| 15 | */
|
---|
| 16 |
|
---|
| 17 | #include "flash_api.h"
|
---|
| 18 | #include "mbed_critical.h"
|
---|
| 19 |
|
---|
| 20 | #if DEVICE_FLASH
|
---|
| 21 | #include "iodefine.h"
|
---|
| 22 | #include "spibsc_iobitmask.h"
|
---|
| 23 | #include "spibsc.h"
|
---|
| 24 | #include "mbed_drv_cfg.h"
|
---|
| 25 |
|
---|
| 26 | /* ---- serial flash command ---- */
|
---|
| 27 | #define SFLASHCMD_SECTOR_ERASE (0x20u) /* SE 3-byte address(1bit) */
|
---|
| 28 | #define SFLASHCMD_PAGE_PROGRAM (0x02u) /* PP 3-byte address(1bit), data(1bit) */
|
---|
| 29 | #define SFLASHCMD_READ_STATUS_REG (0x05u) /* RDSR data(1bit) */
|
---|
| 30 | #define SFLASHCMD_WRITE_ENABLE (0x06u) /* WREN */
|
---|
| 31 | /* ---- serial flash register definitions ---- */
|
---|
| 32 | #define STREG_BUSY_BIT (0x01u) /* SR.[0]BUSY Erase/Write In Progress (RO) */
|
---|
| 33 |
|
---|
| 34 | /* Definition of the base address for the MMU translation table */
|
---|
| 35 | #if defined(__CC_ARM) || defined(__GNUC__)
|
---|
| 36 | extern uint32_t Image$$TTB$$ZI$$Base;
|
---|
| 37 | #define TTB ((uint32_t)&Image$$TTB$$ZI$$Base) /* using linker symbol */
|
---|
| 38 | #elif defined(__ICCARM__)
|
---|
| 39 | #pragma section="TTB"
|
---|
| 40 | #define TTB ((uint32_t)__section_begin("TTB"))
|
---|
| 41 | #endif
|
---|
| 42 |
|
---|
| 43 | typedef struct {
|
---|
| 44 | uint32_t cdb; /* bit-width : command */
|
---|
| 45 | uint32_t ocdb; /* bit-width : optional command */
|
---|
| 46 | uint32_t adb; /* bit-width : address */
|
---|
| 47 | uint32_t opdb; /* bit-width : option data */
|
---|
| 48 | uint32_t spidb; /* bit-width : data */
|
---|
| 49 |
|
---|
| 50 | uint32_t cde; /* Enable : command */
|
---|
| 51 | uint32_t ocde; /* Enable : optional command */
|
---|
| 52 | uint32_t ade; /* Enable : address */
|
---|
| 53 | uint32_t opde; /* Enable : option data */
|
---|
| 54 | uint32_t spide; /* Enable : data */
|
---|
| 55 |
|
---|
| 56 | uint32_t sslkp; /* SPBSSL level */
|
---|
| 57 | uint32_t spire; /* Enable data read */
|
---|
| 58 | uint32_t spiwe; /* Enable data write */
|
---|
| 59 |
|
---|
| 60 | uint32_t dme; /* Enable : dummy cycle */
|
---|
| 61 |
|
---|
| 62 | uint32_t addre; /* DDR enable : address */
|
---|
| 63 | uint32_t opdre; /* DDR enable : option data */
|
---|
| 64 | uint32_t spidre; /* DDR enable : data */
|
---|
| 65 |
|
---|
| 66 | uint8_t dmdb; /* bit-width : dummy cycle */
|
---|
| 67 | uint8_t dmcyc; /* number of dummy cycles */
|
---|
| 68 |
|
---|
| 69 | uint8_t cmd; /* command */
|
---|
| 70 | uint8_t ocmd; /* optional command */
|
---|
| 71 | uint32_t addr; /* address */
|
---|
| 72 | uint8_t opd[4]; /* option data 3/2/1/0 */
|
---|
| 73 | uint32_t smrdr[2]; /* read data */
|
---|
| 74 | uint32_t smwdr[2]; /* write data */
|
---|
| 75 | } st_spibsc_spimd_reg_t;
|
---|
| 76 |
|
---|
| 77 | /* SPI Multi-I/O bus address space address definitions */
|
---|
| 78 | #define SPIBSC_ADDR_START (0x18000000uL)
|
---|
| 79 | #define SPIBSC_ADDR_END (0x1BFFFFFFuL)
|
---|
| 80 |
|
---|
| 81 | typedef struct {
|
---|
| 82 | uint32_t b0 : 1 ; /* bit 0 : - (0) */
|
---|
| 83 | uint32_t b1 : 1 ; /* bit 1 : - (1) */
|
---|
| 84 | uint32_t B : 1 ; /* bit 2 : B Memory region attribute bit */
|
---|
| 85 | uint32_t C : 1 ; /* bit 3 : C Memory region attribute bit */
|
---|
| 86 | uint32_t XN : 1 ; /* bit 4 : XN Execute-never bit */
|
---|
| 87 | uint32_t Domain : 4 ; /* bit 8-5 : Domain Domain field */
|
---|
| 88 | uint32_t b9 : 1 ; /* bit 9 : IMP IMPLEMENTATION DEFINED */
|
---|
| 89 | uint32_t AP1_0 : 2 ; /* bit 11-10 : AP[1:0] Access permissions bits:bit1-0 */
|
---|
| 90 | uint32_t TEX : 3 ; /* bit 14-12 : TEX[2:0] Memory region attribute bits */
|
---|
| 91 | uint32_t AP2 : 1 ; /* bit 15 : AP[2] Access permissions bits:bit2 */
|
---|
| 92 | uint32_t S : 1 ; /* bit 16 : S Shareable bit */
|
---|
| 93 | uint32_t nG : 1 ; /* bit 17 : nG Not global bit */
|
---|
| 94 | uint32_t b18 : 1 ; /* bit 18 : - (0) */
|
---|
| 95 | uint32_t NS : 1 ; /* bit 19 : NS Non-secure bit */
|
---|
| 96 | uint32_t base_addr : 12; /* bit 31-20 : PA[31:20] PA(physical address) bits:bit31-20 */
|
---|
| 97 | } mmu_ttbl_desc_section_t;
|
---|
| 98 |
|
---|
| 99 | static mmu_ttbl_desc_section_t desc_tbl[(SPIBSC_ADDR_END >> 20) - (SPIBSC_ADDR_START >> 20) + 1];
|
---|
| 100 | static volatile struct st_spibsc* SPIBSC = &SPIBSC0;
|
---|
| 101 | static st_spibsc_spimd_reg_t spimd_reg;
|
---|
| 102 |
|
---|
| 103 | #if defined(__ICCARM__)
|
---|
| 104 | #define RAM_CODE_SEC __ramfunc
|
---|
| 105 | #else
|
---|
| 106 | #define RAM_CODE_SEC __attribute__((section("RAM_CODE")))
|
---|
| 107 | #endif
|
---|
| 108 |
|
---|
| 109 | /* Global function for optimization */
|
---|
| 110 | RAM_CODE_SEC int32_t _sector_erase(uint32_t addr);
|
---|
| 111 | RAM_CODE_SEC int32_t _page_program(uint32_t addr, const uint8_t * buf, int32_t size);
|
---|
| 112 |
|
---|
| 113 | static RAM_CODE_SEC int32_t write_enable(void);
|
---|
| 114 | static RAM_CODE_SEC int32_t busy_wait(void);
|
---|
| 115 | static RAM_CODE_SEC int32_t read_register(uint8_t cmd, uint8_t * status);
|
---|
| 116 | static RAM_CODE_SEC int32_t data_send(uint32_t bit_width, uint32_t spbssl_level, const uint8_t * buf, int32_t size);
|
---|
| 117 | static RAM_CODE_SEC void spi_mode(void);
|
---|
| 118 | static RAM_CODE_SEC void ex_mode(void);
|
---|
| 119 | static RAM_CODE_SEC void clear_spimd_reg(st_spibsc_spimd_reg_t * regset);
|
---|
| 120 | static RAM_CODE_SEC int32_t spibsc_transfer(st_spibsc_spimd_reg_t * regset);
|
---|
| 121 | static RAM_CODE_SEC uint32_t RegRead_32(volatile uint32_t * ioreg, uint32_t shift, uint32_t mask);
|
---|
| 122 | static RAM_CODE_SEC void RegWwrite_32(volatile uint32_t * ioreg, uint32_t write_value, uint32_t shift, uint32_t mask);
|
---|
| 123 | static RAM_CODE_SEC void change_mmu_ttbl_spibsc(uint32_t type);
|
---|
| 124 | static RAM_CODE_SEC void spibsc_stop(void);
|
---|
| 125 | static RAM_CODE_SEC void cache_control(void);
|
---|
| 126 |
|
---|
| 127 | int32_t flash_init(flash_t *obj)
|
---|
| 128 | {
|
---|
| 129 | return 0;
|
---|
| 130 | }
|
---|
| 131 |
|
---|
| 132 | int32_t flash_free(flash_t *obj)
|
---|
| 133 | {
|
---|
| 134 | return 0;
|
---|
| 135 | }
|
---|
| 136 |
|
---|
| 137 | int32_t flash_erase_sector(flash_t *obj, uint32_t address)
|
---|
| 138 | {
|
---|
| 139 | int32_t ret;
|
---|
| 140 |
|
---|
| 141 | core_util_critical_section_enter();
|
---|
| 142 | ret = _sector_erase(address - FLASH_BASE);
|
---|
| 143 | core_util_critical_section_exit();
|
---|
| 144 |
|
---|
| 145 | return ret;
|
---|
| 146 | }
|
---|
| 147 |
|
---|
| 148 | int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size)
|
---|
| 149 | {
|
---|
| 150 | int32_t ret;
|
---|
| 151 |
|
---|
| 152 | core_util_critical_section_enter();
|
---|
| 153 | ret = _page_program(address - FLASH_BASE, data, size);
|
---|
| 154 | core_util_critical_section_exit();
|
---|
| 155 |
|
---|
| 156 | return ret;
|
---|
| 157 | }
|
---|
| 158 |
|
---|
| 159 | uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
|
---|
| 160 | {
|
---|
| 161 | if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
|
---|
| 162 | return MBED_FLASH_INVALID_SIZE;
|
---|
| 163 | }
|
---|
| 164 |
|
---|
| 165 | return FLASH_SECTOR_SIZE;
|
---|
| 166 | }
|
---|
| 167 |
|
---|
| 168 | uint32_t flash_get_page_size(const flash_t *obj)
|
---|
| 169 | {
|
---|
| 170 | return 1;
|
---|
| 171 | }
|
---|
| 172 |
|
---|
| 173 | uint32_t flash_get_start_address(const flash_t *obj)
|
---|
| 174 | {
|
---|
| 175 | return FLASH_BASE;
|
---|
| 176 | }
|
---|
| 177 |
|
---|
| 178 | uint32_t flash_get_size(const flash_t *obj)
|
---|
| 179 | {
|
---|
| 180 | return FLASH_SIZE;
|
---|
| 181 | }
|
---|
| 182 |
|
---|
| 183 | int32_t _sector_erase(uint32_t addr)
|
---|
| 184 | {
|
---|
| 185 | int32_t ret;
|
---|
| 186 |
|
---|
| 187 | spi_mode();
|
---|
| 188 |
|
---|
| 189 | /* ---- Write enable ---- */
|
---|
| 190 | ret = write_enable(); /* WREN Command */
|
---|
| 191 | if (ret != 0) {
|
---|
| 192 | ex_mode();
|
---|
| 193 | return ret;
|
---|
| 194 | }
|
---|
| 195 |
|
---|
| 196 | /* ---- spimd_reg init ---- */
|
---|
| 197 | clear_spimd_reg(&spimd_reg);
|
---|
| 198 |
|
---|
| 199 | /* ---- command ---- */
|
---|
| 200 | spimd_reg.cde = SPIBSC_OUTPUT_ENABLE;
|
---|
| 201 | spimd_reg.cdb = SPIBSC_1BIT;
|
---|
| 202 | spimd_reg.cmd = SFLASHCMD_SECTOR_ERASE;
|
---|
| 203 |
|
---|
| 204 | /* ---- address ---- */
|
---|
| 205 | spimd_reg.ade = SPIBSC_OUTPUT_ADDR_24;
|
---|
| 206 | spimd_reg.addre = SPIBSC_SDR_TRANS; /* SDR */
|
---|
| 207 | spimd_reg.adb = SPIBSC_1BIT;
|
---|
| 208 | spimd_reg.addr = addr;
|
---|
| 209 |
|
---|
| 210 | ret = spibsc_transfer(&spimd_reg);
|
---|
| 211 | if (ret != 0) {
|
---|
| 212 | ex_mode();
|
---|
| 213 | return ret;
|
---|
| 214 | }
|
---|
| 215 |
|
---|
| 216 | ret = busy_wait();
|
---|
| 217 |
|
---|
| 218 | ex_mode();
|
---|
| 219 | return ret;
|
---|
| 220 | }
|
---|
| 221 |
|
---|
| 222 | int32_t _page_program(uint32_t addr, const uint8_t * buf, int32_t size)
|
---|
| 223 | {
|
---|
| 224 | int32_t ret;
|
---|
| 225 | int32_t program_size;
|
---|
| 226 | int32_t remainder;
|
---|
| 227 | int32_t idx = 0;
|
---|
| 228 |
|
---|
| 229 | spi_mode();
|
---|
| 230 |
|
---|
| 231 | while (size > 0) {
|
---|
| 232 | if (size > FLASH_PAGE_SIZE) {
|
---|
| 233 | program_size = FLASH_PAGE_SIZE;
|
---|
| 234 | } else {
|
---|
| 235 | program_size = size;
|
---|
| 236 | }
|
---|
| 237 | remainder = FLASH_PAGE_SIZE - (addr % FLASH_PAGE_SIZE);
|
---|
| 238 | if ((remainder != 0) && (program_size > remainder)) {
|
---|
| 239 | program_size = remainder;
|
---|
| 240 | }
|
---|
| 241 |
|
---|
| 242 | /* ---- Write enable ---- */
|
---|
| 243 | ret = write_enable(); /* WREN Command */
|
---|
| 244 | if (ret != 0) {
|
---|
| 245 | ex_mode();
|
---|
| 246 | return ret;
|
---|
| 247 | }
|
---|
| 248 |
|
---|
| 249 | /* ----------- 1. Command, Address ---------------*/
|
---|
| 250 | /* ---- spimd_reg init ---- */
|
---|
| 251 | clear_spimd_reg(&spimd_reg);
|
---|
| 252 |
|
---|
| 253 | /* ---- command ---- */
|
---|
| 254 | spimd_reg.cde = SPIBSC_OUTPUT_ENABLE;
|
---|
| 255 | spimd_reg.cdb = SPIBSC_1BIT;
|
---|
| 256 | spimd_reg.cmd = SFLASHCMD_PAGE_PROGRAM;
|
---|
| 257 |
|
---|
| 258 | /* ---- address ---- */
|
---|
| 259 | spimd_reg.ade = SPIBSC_OUTPUT_ADDR_24;
|
---|
| 260 | spimd_reg.addre = SPIBSC_SDR_TRANS; /* SDR */
|
---|
| 261 | spimd_reg.adb = SPIBSC_1BIT;
|
---|
| 262 | spimd_reg.addr = addr;
|
---|
| 263 |
|
---|
| 264 | /* ---- Others ---- */
|
---|
| 265 | spimd_reg.sslkp = SPIBSC_SPISSL_KEEP; /* SPBSSL level */
|
---|
| 266 |
|
---|
| 267 | ret = spibsc_transfer(&spimd_reg); /* Command,Address */
|
---|
| 268 | if (ret != 0) {
|
---|
| 269 | ex_mode();
|
---|
| 270 | return ret;
|
---|
| 271 | }
|
---|
| 272 |
|
---|
| 273 | /* ----------- 2. Data ---------------*/
|
---|
| 274 | ret = data_send(SPIBSC_1BIT, SPIBSC_SPISSL_NEGATE, &buf[idx], program_size);
|
---|
| 275 | if (ret != 0) {
|
---|
| 276 | ex_mode();
|
---|
| 277 | return ret;
|
---|
| 278 | }
|
---|
| 279 |
|
---|
| 280 | ret = busy_wait();
|
---|
| 281 | if (ret != 0) {
|
---|
| 282 | ex_mode();
|
---|
| 283 | return ret;
|
---|
| 284 | }
|
---|
| 285 |
|
---|
| 286 | addr += program_size;
|
---|
| 287 | idx += program_size;
|
---|
| 288 | size -= program_size;
|
---|
| 289 | }
|
---|
| 290 |
|
---|
| 291 | ex_mode();
|
---|
| 292 | return ret;
|
---|
| 293 | }
|
---|
| 294 |
|
---|
| 295 | static int32_t write_enable(void)
|
---|
| 296 | {
|
---|
| 297 | int32_t ret;
|
---|
| 298 |
|
---|
| 299 | /* ---- spimd_reg init ---- */
|
---|
| 300 | clear_spimd_reg(&spimd_reg);
|
---|
| 301 |
|
---|
| 302 | /* ---- command ---- */
|
---|
| 303 | spimd_reg.cde = SPIBSC_OUTPUT_ENABLE;
|
---|
| 304 | spimd_reg.cdb = SPIBSC_1BIT;
|
---|
| 305 | spimd_reg.cmd = SFLASHCMD_WRITE_ENABLE;
|
---|
| 306 |
|
---|
| 307 | ret = spibsc_transfer(&spimd_reg);
|
---|
| 308 |
|
---|
| 309 | return ret;
|
---|
| 310 | }
|
---|
| 311 |
|
---|
| 312 | static int32_t busy_wait(void)
|
---|
| 313 | {
|
---|
| 314 | int32_t ret;
|
---|
| 315 | uint8_t st_reg;
|
---|
| 316 |
|
---|
| 317 | while (1) {
|
---|
| 318 | ret = read_register(SFLASHCMD_READ_STATUS_REG, &st_reg);
|
---|
| 319 | if (ret != 0) {
|
---|
| 320 | break;
|
---|
| 321 | }
|
---|
| 322 | if ((st_reg & STREG_BUSY_BIT) == 0) {
|
---|
| 323 | break;
|
---|
| 324 | }
|
---|
| 325 | }
|
---|
| 326 |
|
---|
| 327 | return ret;
|
---|
| 328 | }
|
---|
| 329 |
|
---|
| 330 | static int32_t read_register(uint8_t cmd, uint8_t * status)
|
---|
| 331 | {
|
---|
| 332 | int32_t ret;
|
---|
| 333 |
|
---|
| 334 | /* ---- spimd_reg init ---- */
|
---|
| 335 | clear_spimd_reg(&spimd_reg);
|
---|
| 336 |
|
---|
| 337 | /* ---- command ---- */
|
---|
| 338 | spimd_reg.cde = SPIBSC_OUTPUT_ENABLE;
|
---|
| 339 | spimd_reg.cdb = SPIBSC_1BIT;
|
---|
| 340 | spimd_reg.cmd = cmd;
|
---|
| 341 |
|
---|
| 342 | /* ---- Others ---- */
|
---|
| 343 | spimd_reg.sslkp = SPIBSC_SPISSL_NEGATE; /* SPBSSL level */
|
---|
| 344 | spimd_reg.spire = SPIBSC_SPIDATA_ENABLE; /* read enable/disable */
|
---|
| 345 | spimd_reg.spiwe = SPIBSC_SPIDATA_ENABLE; /* write enable/disable */
|
---|
| 346 |
|
---|
| 347 | /* ---- data ---- */
|
---|
| 348 | spimd_reg.spide = SPIBSC_OUTPUT_SPID_8; /* Enable(8bit) */
|
---|
| 349 | spimd_reg.spidre = SPIBSC_SDR_TRANS; /* SDR */
|
---|
| 350 | spimd_reg.spidb = SPIBSC_1BIT;
|
---|
| 351 | spimd_reg.smwdr[0] = 0x00; /* Output 0 in read status */
|
---|
| 352 | spimd_reg.smwdr[1] = 0x00; /* Output 0 in read status */
|
---|
| 353 |
|
---|
| 354 | ret = spibsc_transfer(&spimd_reg);
|
---|
| 355 | if (ret == 0) {
|
---|
| 356 | *status = (uint8_t)(spimd_reg.smrdr[0]); /* Data[7:0] */
|
---|
| 357 | }
|
---|
| 358 |
|
---|
| 359 | return ret;
|
---|
| 360 | }
|
---|
| 361 |
|
---|
| 362 | static int32_t data_send(uint32_t bit_width, uint32_t spbssl_level, const uint8_t * buf, int32_t size)
|
---|
| 363 | {
|
---|
| 364 | int32_t ret = 0;
|
---|
| 365 | int32_t unit;
|
---|
| 366 | uint8_t *buf_b;
|
---|
| 367 | uint16_t *buf_s;
|
---|
| 368 | uint32_t *buf_l;
|
---|
| 369 |
|
---|
| 370 | /* ---- spimd_reg init ---- */
|
---|
| 371 | clear_spimd_reg(&spimd_reg);
|
---|
| 372 |
|
---|
| 373 | /* ---- Others ---- */
|
---|
| 374 | spimd_reg.sslkp = SPIBSC_SPISSL_KEEP; /* SPBSSL level */
|
---|
| 375 | spimd_reg.spiwe = SPIBSC_SPIDATA_ENABLE; /* write enable/disable */
|
---|
| 376 |
|
---|
| 377 | /* ---- data ---- */
|
---|
| 378 | spimd_reg.spidb = bit_width;
|
---|
| 379 | spimd_reg.spidre= SPIBSC_SDR_TRANS; /* SDR */
|
---|
| 380 |
|
---|
| 381 | if (((uint32_t)size & 0x3) == 0) {
|
---|
| 382 | spimd_reg.spide = SPIBSC_OUTPUT_SPID_32; /* Enable(32bit) */
|
---|
| 383 | unit = 4;
|
---|
| 384 | } else if (((uint32_t)size & 0x1) == 0) {
|
---|
| 385 | spimd_reg.spide = SPIBSC_OUTPUT_SPID_16; /* Enable(16bit) */
|
---|
| 386 | unit = 2;
|
---|
| 387 | } else {
|
---|
| 388 | spimd_reg.spide = SPIBSC_OUTPUT_SPID_8; /* Enable(8bit) */
|
---|
| 389 | unit = 1;
|
---|
| 390 | }
|
---|
| 391 |
|
---|
| 392 | while (size > 0) {
|
---|
| 393 | if (unit == 1) {
|
---|
| 394 | buf_b = (uint8_t *)buf;
|
---|
| 395 | spimd_reg.smwdr[0] = (uint32_t)(((uint32_t)*buf_b) & 0x000000FF);
|
---|
| 396 | } else if (unit == 2) {
|
---|
| 397 | buf_s = (uint16_t *)buf;
|
---|
| 398 | spimd_reg.smwdr[0] = (uint32_t)(((uint32_t)*buf_s) & 0x0000FFFF);
|
---|
| 399 | } else if (unit == 4) {
|
---|
| 400 | buf_l = (uint32_t *)buf;
|
---|
| 401 | spimd_reg.smwdr[0] = (uint32_t)(((uint32_t)(*buf_l)) & 0xfffffffful);
|
---|
| 402 | } else {
|
---|
| 403 | /* Do Nothing */
|
---|
| 404 | }
|
---|
| 405 |
|
---|
| 406 | buf += unit;
|
---|
| 407 | size -= unit;
|
---|
| 408 |
|
---|
| 409 | if (size <= 0) {
|
---|
| 410 | spimd_reg.sslkp = spbssl_level;
|
---|
| 411 | }
|
---|
| 412 |
|
---|
| 413 | ret = spibsc_transfer(&spimd_reg); /* Data */
|
---|
| 414 | if (ret != 0) {
|
---|
| 415 | return ret;
|
---|
| 416 | }
|
---|
| 417 | }
|
---|
| 418 |
|
---|
| 419 | return ret;
|
---|
| 420 | }
|
---|
| 421 |
|
---|
| 422 | static void spi_mode(void)
|
---|
| 423 | {
|
---|
| 424 | volatile uint32_t dummy_read_32;
|
---|
| 425 |
|
---|
| 426 | if (RegRead_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD) != SPIBSC_CMNCR_MD_SPI) {
|
---|
| 427 | /* ==== Change the MMU translation table SPI Multi-I/O bus space settings
|
---|
| 428 | for use in SPI operating mode ==== */
|
---|
| 429 | change_mmu_ttbl_spibsc(0);
|
---|
| 430 |
|
---|
| 431 | /* ==== Cleaning and invalidation of cache ==== */
|
---|
| 432 | cache_control();
|
---|
| 433 |
|
---|
| 434 | /* ==== Switch to SPI operating mode ==== */
|
---|
| 435 | spibsc_stop();
|
---|
| 436 |
|
---|
| 437 | dummy_read_32 = SPIBSC->CMNCR; /* dummy read */
|
---|
| 438 | /* SPI Mode */
|
---|
| 439 | RegWwrite_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_SPI, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD);
|
---|
| 440 | dummy_read_32 = SPIBSC->CMNCR; /* dummy read */
|
---|
| 441 |
|
---|
| 442 | }
|
---|
| 443 | (void)dummy_read_32;
|
---|
| 444 | }
|
---|
| 445 |
|
---|
| 446 | static void ex_mode(void)
|
---|
| 447 | {
|
---|
| 448 | volatile uint32_t dummy_read_32;
|
---|
| 449 |
|
---|
| 450 | if (RegRead_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD) != SPIBSC_CMNCR_MD_EXTRD) {
|
---|
| 451 | /* ==== Switch to external address space read mode and clear SPIBSC read cache ==== */
|
---|
| 452 | spibsc_stop();
|
---|
| 453 |
|
---|
| 454 | /* Flush SPIBSC's read cache */
|
---|
| 455 | RegWwrite_32(&SPIBSC->DRCR, SPIBSC_DRCR_RCF_EXE, SPIBSC_DRCR_RCF_SHIFT, SPIBSC_DRCR_RCF);
|
---|
| 456 | dummy_read_32 = SPIBSC->DRCR; /* dummy read */
|
---|
| 457 |
|
---|
| 458 | /* External address space read mode */
|
---|
| 459 | RegWwrite_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_EXTRD, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD);
|
---|
| 460 | dummy_read_32 = SPIBSC->CMNCR; /* dummy read */
|
---|
| 461 |
|
---|
| 462 | /* ==== Change the MMU translation table SPI Multi-I/O bus space settings
|
---|
| 463 | for use in external address space read mode ==== */
|
---|
| 464 | change_mmu_ttbl_spibsc(1);
|
---|
| 465 |
|
---|
| 466 | /* ==== Cleaning and invalidation of cache ==== */
|
---|
| 467 | cache_control();
|
---|
| 468 | }
|
---|
| 469 | (void)dummy_read_32;
|
---|
| 470 | }
|
---|
| 471 |
|
---|
| 472 | static void clear_spimd_reg(st_spibsc_spimd_reg_t * regset)
|
---|
| 473 | {
|
---|
| 474 | /* ---- command ---- */
|
---|
| 475 | regset->cde = SPIBSC_OUTPUT_DISABLE;
|
---|
| 476 | regset->cdb = SPIBSC_1BIT;
|
---|
| 477 | regset->cmd = 0x00;
|
---|
| 478 |
|
---|
| 479 | /* ---- optional command ---- */
|
---|
| 480 | regset->ocde = SPIBSC_OUTPUT_DISABLE;
|
---|
| 481 | regset->ocdb = SPIBSC_1BIT;
|
---|
| 482 | regset->ocmd = 0x00;
|
---|
| 483 |
|
---|
| 484 | /* ---- address ---- */
|
---|
| 485 | regset->ade = SPIBSC_OUTPUT_DISABLE;
|
---|
| 486 | regset->addre = SPIBSC_SDR_TRANS; /* SDR */
|
---|
| 487 | regset->adb = SPIBSC_1BIT;
|
---|
| 488 | regset->addr = 0x00000000;
|
---|
| 489 |
|
---|
| 490 | /* ---- option data ---- */
|
---|
| 491 | regset->opde = SPIBSC_OUTPUT_DISABLE;
|
---|
| 492 | regset->opdre = SPIBSC_SDR_TRANS; /* SDR */
|
---|
| 493 | regset->opdb = SPIBSC_1BIT;
|
---|
| 494 | regset->opd[0] = 0x00; /* OPD3 */
|
---|
| 495 | regset->opd[1] = 0x00; /* OPD2 */
|
---|
| 496 | regset->opd[2] = 0x00; /* OPD1 */
|
---|
| 497 | regset->opd[3] = 0x00; /* OPD0 */
|
---|
| 498 |
|
---|
| 499 | /* ---- dummy cycle ---- */
|
---|
| 500 | regset->dme = SPIBSC_DUMMY_CYC_DISABLE;
|
---|
| 501 | regset->dmdb = SPIBSC_1BIT;
|
---|
| 502 | regset->dmcyc = SPIBSC_DUMMY_1CYC;
|
---|
| 503 |
|
---|
| 504 | /* ---- data ---- */
|
---|
| 505 | regset->spide = SPIBSC_OUTPUT_DISABLE;
|
---|
| 506 | regset->spidre = SPIBSC_SDR_TRANS; /* SDR */
|
---|
| 507 | regset->spidb = SPIBSC_1BIT;
|
---|
| 508 |
|
---|
| 509 | /* ---- Others ---- */
|
---|
| 510 | regset->sslkp = SPIBSC_SPISSL_NEGATE; /* SPBSSL level */
|
---|
| 511 | regset->spire = SPIBSC_SPIDATA_DISABLE; /* read enable/disable */
|
---|
| 512 | regset->spiwe = SPIBSC_SPIDATA_DISABLE; /* write enable/disable */
|
---|
| 513 | }
|
---|
| 514 |
|
---|
| 515 | static int32_t spibsc_transfer(st_spibsc_spimd_reg_t * regset)
|
---|
| 516 | {
|
---|
| 517 | if (RegRead_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD) != SPIBSC_CMNCR_MD_SPI) {
|
---|
| 518 | if (RegRead_32(&SPIBSC->CMNSR, SPIBSC_CMNSR_SSLF_SHIFT, SPIBSC_CMNSR_SSLF) != SPIBSC_SSL_NEGATE) {
|
---|
| 519 | return -1;
|
---|
| 520 | }
|
---|
| 521 | /* SPI Mode */
|
---|
| 522 | RegWwrite_32(&SPIBSC->CMNCR, SPIBSC_CMNCR_MD_SPI, SPIBSC_CMNCR_MD_SHIFT, SPIBSC_CMNCR_MD);
|
---|
| 523 | }
|
---|
| 524 |
|
---|
| 525 | if (RegRead_32(&SPIBSC->CMNSR, SPIBSC_CMNSR_TEND_SHIFT, SPIBSC_CMNSR_TEND) != SPIBSC_TRANS_END) {
|
---|
| 526 | return -1;
|
---|
| 527 | }
|
---|
| 528 |
|
---|
| 529 | /* ---- Command ---- */
|
---|
| 530 | /* Enable/Disable */
|
---|
| 531 | RegWwrite_32(&SPIBSC->SMENR, regset->cde, SPIBSC_SMENR_CDE_SHIFT, SPIBSC_SMENR_CDE);
|
---|
| 532 | if (regset->cde != SPIBSC_OUTPUT_DISABLE) {
|
---|
| 533 | /* Command */
|
---|
| 534 | RegWwrite_32(&SPIBSC->SMCMR, regset->cmd, SPIBSC_SMCMR_CMD_SHIFT, SPIBSC_SMCMR_CMD);
|
---|
| 535 | /* Single/Dual/Quad */
|
---|
| 536 | RegWwrite_32(&SPIBSC->SMENR, regset->cdb, SPIBSC_SMENR_CDB_SHIFT, SPIBSC_SMENR_CDB);
|
---|
| 537 | }
|
---|
| 538 |
|
---|
| 539 | /* ---- Option Command ---- */
|
---|
| 540 | /* Enable/Disable */
|
---|
| 541 | RegWwrite_32(&SPIBSC->SMENR, regset->ocde, SPIBSC_SMENR_OCDE_SHIFT, SPIBSC_SMENR_OCDE);
|
---|
| 542 | if (regset->ocde != SPIBSC_OUTPUT_DISABLE) {
|
---|
| 543 | /* Option Command */
|
---|
| 544 | RegWwrite_32(&SPIBSC->SMCMR, regset->ocmd, SPIBSC_SMCMR_OCMD_SHIFT, SPIBSC_SMCMR_OCMD);
|
---|
| 545 | /* Single/Dual/Quad */
|
---|
| 546 | RegWwrite_32(&SPIBSC->SMENR, regset->ocdb, SPIBSC_SMENR_OCDB_SHIFT, SPIBSC_SMENR_OCDB);
|
---|
| 547 | }
|
---|
| 548 |
|
---|
| 549 | /* ---- Address ---- */
|
---|
| 550 | /* Enable/Disable */
|
---|
| 551 | RegWwrite_32(&SPIBSC->SMENR, regset->ade, SPIBSC_SMENR_ADE_SHIFT, SPIBSC_SMENR_ADE);
|
---|
| 552 | if (regset->ade != SPIBSC_OUTPUT_DISABLE) {
|
---|
| 553 | /* Address */
|
---|
| 554 | RegWwrite_32(&SPIBSC->SMADR, regset->addr, SPIBSC_SMADR_ADR_SHIFT, SPIBSC_SMADR_ADR);
|
---|
| 555 | /* Single/Dual/Quad */
|
---|
| 556 | RegWwrite_32(&SPIBSC->SMENR, regset->adb, SPIBSC_SMENR_ADB_SHIFT, SPIBSC_SMENR_ADB);
|
---|
| 557 | }
|
---|
| 558 |
|
---|
| 559 | /* ---- Option Data ---- */
|
---|
| 560 | /* Enable/Disable */
|
---|
| 561 | RegWwrite_32(&SPIBSC->SMENR, regset->opde, SPIBSC_SMENR_OPDE_SHIFT, SPIBSC_SMENR_OPDE);
|
---|
| 562 | if (regset->opde != SPIBSC_OUTPUT_DISABLE) {
|
---|
| 563 | /* Option Data */
|
---|
| 564 | RegWwrite_32(&SPIBSC->SMOPR, regset->opd[0], SPIBSC_SMOPR_OPD3_SHIFT, SPIBSC_SMOPR_OPD3);
|
---|
| 565 | RegWwrite_32(&SPIBSC->SMOPR, regset->opd[1], SPIBSC_SMOPR_OPD2_SHIFT, SPIBSC_SMOPR_OPD2);
|
---|
| 566 | RegWwrite_32(&SPIBSC->SMOPR, regset->opd[2], SPIBSC_SMOPR_OPD1_SHIFT, SPIBSC_SMOPR_OPD1);
|
---|
| 567 | RegWwrite_32(&SPIBSC->SMOPR, regset->opd[3], SPIBSC_SMOPR_OPD0_SHIFT, SPIBSC_SMOPR_OPD0);
|
---|
| 568 | /* Single/Dual/Quad */
|
---|
| 569 | RegWwrite_32(&SPIBSC->SMENR, regset->opdb, SPIBSC_SMENR_OPDB_SHIFT, SPIBSC_SMENR_OPDB);
|
---|
| 570 | }
|
---|
| 571 |
|
---|
| 572 | /* ---- Dummy ---- */
|
---|
| 573 | /* Enable/Disable */
|
---|
| 574 | RegWwrite_32(&SPIBSC->SMENR, regset->dme, SPIBSC_SMENR_DME_SHIFT, SPIBSC_SMENR_DME);
|
---|
| 575 | if (regset->dme != SPIBSC_DUMMY_CYC_DISABLE) {
|
---|
| 576 | RegWwrite_32(&SPIBSC->SMDMCR, regset->dmdb, SPIBSC_SMDMCR_DMDB_SHIFT, SPIBSC_SMDMCR_DMDB);
|
---|
| 577 | /* Dummy Cycle */
|
---|
| 578 | RegWwrite_32(&SPIBSC->SMDMCR, regset->dmcyc, SPIBSC_SMDMCR_DMCYC_SHIFT, SPIBSC_SMDMCR_DMCYC);
|
---|
| 579 | }
|
---|
| 580 |
|
---|
| 581 | /* ---- Data ---- */
|
---|
| 582 | /* Enable/Disable */
|
---|
| 583 | RegWwrite_32(&SPIBSC->SMENR, regset->spide, SPIBSC_SMENR_SPIDE_SHIFT, SPIBSC_SMENR_SPIDE);
|
---|
| 584 | if (regset->spide != SPIBSC_OUTPUT_DISABLE) {
|
---|
| 585 | if (SPIBSC_OUTPUT_SPID_8 == regset->spide) {
|
---|
| 586 | if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) {
|
---|
| 587 | SPIBSC->SMWDR0.UINT8[0] = (uint8_t)(regset->smwdr[0]);
|
---|
| 588 | } else {
|
---|
| 589 | SPIBSC->SMWDR0.UINT16[0] = (uint16_t)(regset->smwdr[0]);
|
---|
| 590 | }
|
---|
| 591 | } else if (regset->spide == SPIBSC_OUTPUT_SPID_16) {
|
---|
| 592 | if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) {
|
---|
| 593 | SPIBSC->SMWDR0.UINT16[0] = (uint16_t)(regset->smwdr[0]);
|
---|
| 594 | } else {
|
---|
| 595 | SPIBSC->SMWDR0.UINT32 = regset->smwdr[0];
|
---|
| 596 | }
|
---|
| 597 | } else if (regset->spide == SPIBSC_OUTPUT_SPID_32) {
|
---|
| 598 | if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) {
|
---|
| 599 | SPIBSC->SMWDR0.UINT32 = (uint32_t)(regset->smwdr[0]);
|
---|
| 600 | } else {
|
---|
| 601 | SPIBSC->SMWDR0.UINT32 = (uint32_t)(regset->smwdr[0]);
|
---|
| 602 | SPIBSC->SMWDR1.UINT32 = (uint32_t)(regset->smwdr[1]); /* valid in two serial-flash */
|
---|
| 603 | }
|
---|
| 604 | } else {
|
---|
| 605 | /* none */
|
---|
| 606 | }
|
---|
| 607 |
|
---|
| 608 | /* Single/Dual/Quad */
|
---|
| 609 | RegWwrite_32(&SPIBSC->SMENR, regset->spidb, SPIBSC_SMENR_SPIDB_SHIFT, SPIBSC_SMENR_SPIDB);
|
---|
| 610 | }
|
---|
| 611 |
|
---|
| 612 | RegWwrite_32(&SPIBSC->SMCR, regset->sslkp, SPIBSC_SMCR_SSLKP_SHIFT, SPIBSC_SMCR_SSLKP);
|
---|
| 613 |
|
---|
| 614 | if ((regset->spidb != SPIBSC_1BIT) && (regset->spide != SPIBSC_OUTPUT_DISABLE)) {
|
---|
| 615 | if ((regset->spire == SPIBSC_SPIDATA_ENABLE) && (regset->spiwe == SPIBSC_SPIDATA_ENABLE)) {
|
---|
| 616 | /* not set in same time */
|
---|
| 617 | return -1;
|
---|
| 618 | }
|
---|
| 619 | }
|
---|
| 620 |
|
---|
| 621 | RegWwrite_32(&SPIBSC->SMCR, regset->spire, SPIBSC_SMCR_SPIRE_SHIFT, SPIBSC_SMCR_SPIRE);
|
---|
| 622 | RegWwrite_32(&SPIBSC->SMCR, regset->spiwe, SPIBSC_SMCR_SPIWE_SHIFT, SPIBSC_SMCR_SPIWE);
|
---|
| 623 |
|
---|
| 624 | /* SDR Transmission/DDR Transmission Setting */
|
---|
| 625 | RegWwrite_32(&SPIBSC->SMDRENR, regset->addre, SPIBSC_SMDRENR_ADDRE_SHIFT, SPIBSC_SMDRENR_ADDRE);
|
---|
| 626 | RegWwrite_32(&SPIBSC->SMDRENR, regset->opdre, SPIBSC_SMDRENR_OPDRE_SHIFT, SPIBSC_SMDRENR_OPDRE);
|
---|
| 627 | RegWwrite_32(&SPIBSC->SMDRENR, regset->spidre, SPIBSC_SMDRENR_SPIDRE_SHIFT, SPIBSC_SMDRENR_SPIDRE);
|
---|
| 628 |
|
---|
| 629 | /* execute after setting SPNDL bit */
|
---|
| 630 | RegWwrite_32(&SPIBSC->SMCR, SPIBSC_SPI_ENABLE, SPIBSC_SMCR_SPIE_SHIFT, SPIBSC_SMCR_SPIE);
|
---|
| 631 |
|
---|
| 632 | /* wait for transfer-start */
|
---|
| 633 | while (RegRead_32(&SPIBSC->CMNSR, SPIBSC_CMNSR_TEND_SHIFT, SPIBSC_CMNSR_TEND) != SPIBSC_TRANS_END) {
|
---|
| 634 | /* wait for transfer-end */
|
---|
| 635 | }
|
---|
| 636 |
|
---|
| 637 | if (SPIBSC_OUTPUT_SPID_8 == regset->spide) {
|
---|
| 638 | if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) {
|
---|
| 639 | regset->smrdr[0] = SPIBSC->SMRDR0.UINT8[0];
|
---|
| 640 | } else {
|
---|
| 641 | regset->smrdr[0] = SPIBSC->SMRDR0.UINT16[0]; /* valid in two serial-flash */
|
---|
| 642 | }
|
---|
| 643 | } else if (regset->spide == SPIBSC_OUTPUT_SPID_16) {
|
---|
| 644 | if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) {
|
---|
| 645 | regset->smrdr[0] = SPIBSC->SMRDR0.UINT16[0];
|
---|
| 646 | } else {
|
---|
| 647 | regset->smrdr[0] = SPIBSC->SMRDR0.UINT32; /* valid in two serial-flash */
|
---|
| 648 | }
|
---|
| 649 | } else if (regset->spide == SPIBSC_OUTPUT_SPID_32) {
|
---|
| 650 | if (RegRead_32(&SPIBSC0.CMNCR, SPIBSC_CMNCR_BSZ_SHIFT, SPIBSC_CMNCR_BSZ) == SPIBSC_CMNCR_BSZ_SINGLE) {
|
---|
| 651 | regset->smrdr[0] = SPIBSC->SMRDR0.UINT32;
|
---|
| 652 | } else {
|
---|
| 653 | regset->smrdr[0] = SPIBSC->SMRDR0.UINT32; /* valid in two serial-flash */
|
---|
| 654 | regset->smrdr[1] = SPIBSC->SMRDR1.UINT32;
|
---|
| 655 | }
|
---|
| 656 | } else {
|
---|
| 657 | /* none */
|
---|
| 658 | }
|
---|
| 659 |
|
---|
| 660 | return 0;
|
---|
| 661 | }
|
---|
| 662 |
|
---|
| 663 | static uint32_t RegRead_32(volatile uint32_t * ioreg, uint32_t shift, uint32_t mask)
|
---|
| 664 | {
|
---|
| 665 | uint32_t reg_value;
|
---|
| 666 |
|
---|
| 667 | reg_value = *ioreg; /* Read from register */
|
---|
| 668 | reg_value = (reg_value & mask) >> shift; /* Clear other bit and Bit shift */
|
---|
| 669 |
|
---|
| 670 | return reg_value;
|
---|
| 671 | }
|
---|
| 672 |
|
---|
| 673 | static void RegWwrite_32(volatile uint32_t * ioreg, uint32_t write_value, uint32_t shift, uint32_t mask)
|
---|
| 674 | {
|
---|
| 675 | uint32_t reg_value;
|
---|
| 676 |
|
---|
| 677 | reg_value = *ioreg; /* Read from register */
|
---|
| 678 | reg_value = (reg_value & (~mask)) | (write_value << shift); /* Modify value */
|
---|
| 679 | *ioreg = reg_value; /* Write to register */
|
---|
| 680 | }
|
---|
| 681 |
|
---|
| 682 | static void change_mmu_ttbl_spibsc(uint32_t type)
|
---|
| 683 | {
|
---|
| 684 | uint32_t index; /* Loop variable: table index */
|
---|
| 685 | mmu_ttbl_desc_section_t desc; /* Loop variable: descriptor */
|
---|
| 686 | mmu_ttbl_desc_section_t * table = (mmu_ttbl_desc_section_t *)TTB;
|
---|
| 687 |
|
---|
| 688 | /* ==== Modify SPI Multi-I/O bus space settings in the MMU translation table ==== */
|
---|
| 689 | for (index = (SPIBSC_ADDR_START >> 20); index <= (SPIBSC_ADDR_END >> 20); index++) {
|
---|
| 690 | /* Modify memory attribute descriptor */
|
---|
| 691 | if (type == 0) { /* Spi */
|
---|
| 692 | desc = table[index];
|
---|
| 693 | desc_tbl[index - (SPIBSC_ADDR_START >> 20)] = desc;
|
---|
| 694 | desc.AP1_0 = 0x0u; /* AP[2:0] = b'000 (No access) */
|
---|
| 695 | desc.AP2 = 0x0u;
|
---|
| 696 | desc.XN = 0x1u; /* XN = 1 (Execute never) */
|
---|
| 697 | } else { /* Xip */
|
---|
| 698 | desc = desc_tbl[index - (SPIBSC_ADDR_START >> 20)];
|
---|
| 699 | }
|
---|
| 700 | /* Write descriptor back to translation table */
|
---|
| 701 | table[index] = desc;
|
---|
| 702 | }
|
---|
| 703 | }
|
---|
| 704 |
|
---|
| 705 | static void spibsc_stop(void)
|
---|
| 706 | {
|
---|
| 707 | if (((SPIBSC->DRCR & SPIBSC_DRCR_RBE) != 0) &&
|
---|
| 708 | ((SPIBSC->DRCR & SPIBSC_DRCR_SSLE) != 0)) {
|
---|
| 709 | RegWwrite_32(&SPIBSC->DRCR, 1, SPIBSC_DRCR_SSLN_SHIFT, SPIBSC_DRCR_SSLN);
|
---|
| 710 | }
|
---|
| 711 |
|
---|
| 712 | while (RegRead_32(&SPIBSC->CMNSR, SPIBSC_CMNSR_SSLF_SHIFT, SPIBSC_CMNSR_SSLF) != SPIBSC_SSL_NEGATE) {
|
---|
| 713 | ;
|
---|
| 714 | }
|
---|
| 715 |
|
---|
| 716 | while (RegRead_32(&SPIBSC->CMNSR, SPIBSC_CMNSR_TEND_SHIFT, SPIBSC_CMNSR_TEND) != SPIBSC_TRANS_END) {
|
---|
| 717 | ;
|
---|
| 718 | }
|
---|
| 719 | }
|
---|
| 720 |
|
---|
| 721 | static void cache_control(void)
|
---|
| 722 | {
|
---|
| 723 | unsigned int assoc;
|
---|
| 724 |
|
---|
| 725 | /* ==== Cleaning and invalidation of the L1 data cache ==== */
|
---|
| 726 | L1C_CleanInvalidateDCacheAll();
|
---|
| 727 | __DSB();
|
---|
| 728 |
|
---|
| 729 | /* ==== Cleaning and invalidation of the L2 cache ==== */
|
---|
| 730 | if (L2C_310->AUX_CNT & (1U << 16U)) {
|
---|
| 731 | assoc = 16U;
|
---|
| 732 | } else {
|
---|
| 733 | assoc = 8U;
|
---|
| 734 | }
|
---|
| 735 | L2C_310->CLEAN_INV_WAY = (1U << assoc) - 1U;
|
---|
| 736 | while (L2C_310->CLEAN_INV_WAY & ((1U << assoc) - 1U)); // poll invalidate
|
---|
| 737 | L2C_310->CACHE_SYNC = 0x0;
|
---|
| 738 |
|
---|
| 739 | /* ==== Invalidate all TLB entries ==== */
|
---|
| 740 | __set_TLBIALL(0);
|
---|
| 741 | __DSB(); // ensure completion of the invalidation
|
---|
| 742 | __ISB(); // ensure instruction fetch path sees new state
|
---|
| 743 |
|
---|
| 744 | /* ==== Invalidate the L1 instruction cache ==== */
|
---|
| 745 | __set_ICIALLU(0);
|
---|
| 746 | __DSB(); // ensure completion of the invalidation
|
---|
| 747 | __ISB(); // ensure instruction fetch path sees new I cache state
|
---|
| 748 | }
|
---|
| 749 | #endif
|
---|