source: asp3_tinet_ecnl_arm/trunk/asp3_dcre/mbed/targets/TARGET_RENESAS/TARGET_RZA1XX/flash_api.c@ 374

Last change on this file since 374 was 374, checked in by coas-nagasima, 5 years ago

mbed関連を更新
シリアルドライバをmbedのHALを使うよう変更
ファイルディスクリプタの処理を更新

  • Property charset set to UTF-8
  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 26.0 KB
Line 
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__)
36extern 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
43typedef 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
81typedef 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
99static mmu_ttbl_desc_section_t desc_tbl[(SPIBSC_ADDR_END >> 20) - (SPIBSC_ADDR_START >> 20) + 1];
100static volatile struct st_spibsc* SPIBSC = &SPIBSC0;
101static 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 */
110RAM_CODE_SEC int32_t _sector_erase(uint32_t addr);
111RAM_CODE_SEC int32_t _page_program(uint32_t addr, const uint8_t * buf, int32_t size);
112
113static RAM_CODE_SEC int32_t write_enable(void);
114static RAM_CODE_SEC int32_t busy_wait(void);
115static RAM_CODE_SEC int32_t read_register(uint8_t cmd, uint8_t * status);
116static RAM_CODE_SEC int32_t data_send(uint32_t bit_width, uint32_t spbssl_level, const uint8_t * buf, int32_t size);
117static RAM_CODE_SEC void spi_mode(void);
118static RAM_CODE_SEC void ex_mode(void);
119static RAM_CODE_SEC void clear_spimd_reg(st_spibsc_spimd_reg_t * regset);
120static RAM_CODE_SEC int32_t spibsc_transfer(st_spibsc_spimd_reg_t * regset);
121static RAM_CODE_SEC uint32_t RegRead_32(volatile uint32_t * ioreg, uint32_t shift, uint32_t mask);
122static RAM_CODE_SEC void RegWwrite_32(volatile uint32_t * ioreg, uint32_t write_value, uint32_t shift, uint32_t mask);
123static RAM_CODE_SEC void change_mmu_ttbl_spibsc(uint32_t type);
124static RAM_CODE_SEC void spibsc_stop(void);
125static RAM_CODE_SEC void cache_control(void);
126
127int32_t flash_init(flash_t *obj)
128{
129 return 0;
130}
131
132int32_t flash_free(flash_t *obj)
133{
134 return 0;
135}
136
137int32_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
148int32_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
159uint32_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
168uint32_t flash_get_page_size(const flash_t *obj)
169{
170 return 1;
171}
172
173uint32_t flash_get_start_address(const flash_t *obj)
174{
175 return FLASH_BASE;
176}
177
178uint32_t flash_get_size(const flash_t *obj)
179{
180 return FLASH_SIZE;
181}
182
183int32_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
222int32_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
295static 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
312static 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
330static 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
362static 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
422static 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
446static 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
472static 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
515static 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
663static 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
673static 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
682static 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
705static 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
721static 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
Note: See TracBrowser for help on using the repository browser.