mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
188:bcfe06ba3d64
mbed library release version 165

Who changed what in which revision?

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