File indexing completed on 2025-05-11 08:22:43
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 #include <string.h>
0044 #include <stdio.h>
0045 #include <inttypes.h>
0046 #include <bsp/hwlib.h>
0047 #include <bsp/alt_clock_manager.h>
0048 #include "alt_qspi.h"
0049 #include <bsp/alt_qspi_private.h>
0050 #include <bsp/socal/alt_qspi.h>
0051 #include <bsp/socal/alt_rstmgr.h>
0052 #include <bsp/socal/alt_sysmgr.h>
0053 #include <bsp/socal/hps.h>
0054 #include <bsp/socal/socal.h>
0055
0056
0057
0058
0059
0060 #define dprintf(...)
0061
0062
0063
0064
0065 #define MIN(a, b) ((a) > (b) ? (b) : (a))
0066
0067
0068 #define ALT_QSPI_CLK_FREQ_MIN ((alt_freq_t)0)
0069 #define ALT_QSPI_CLK_FREQ_MAX ((alt_freq_t)432000000)
0070
0071
0072 #define ALT_QSPI_INT_STATUS_ALL ( \
0073 ALT_QSPI_INT_STATUS_MODE_FAIL | \
0074 ALT_QSPI_INT_STATUS_UFL | \
0075 ALT_QSPI_INT_STATUS_IDAC_OP_COMPLETE | \
0076 ALT_QSPI_INT_STATUS_IDAC_OP_REJECT | \
0077 ALT_QSPI_INT_STATUS_WR_PROT_VIOL | \
0078 ALT_QSPI_INT_STATUS_ILL_AHB_ACCESS | \
0079 ALT_QSPI_INT_STATUS_IDAC_WTRMK_TRIG | \
0080 ALT_QSPI_INT_STATUS_RX_OVF | \
0081 ALT_QSPI_INT_STATUS_TX_FIFO_NOT_FULL | \
0082 ALT_QSPI_INT_STATUS_TX_FIFO_FULL | \
0083 ALT_QSPI_INT_STATUS_RX_FIFO_NOT_EMPTY | \
0084 ALT_QSPI_INT_STATUS_RX_FIFO_FULL | \
0085 ALT_QSPI_INT_STATUS_IDAC_RD_FULL \
0086 )
0087
0088 static uint32_t qspi_device_size = 0;
0089
0090
0091
0092 static ALT_STATUS_CODE alt_qspi_device_status(uint32_t * status)
0093 {
0094
0095 return alt_qspi_stig_rd_cmd(ALT_QSPI_STIG_OPCODE_RDSR, 0, 1, status, 10000);
0096 }
0097
0098 #if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT
0099 static ALT_STATUS_CODE alt_qspi_N25Q_device_flag(uint32_t * flagsr)
0100 {
0101 if (qspi_device_size < 0x4000000)
0102 {
0103 return ALT_E_SUCCESS;
0104 }
0105
0106
0107 return alt_qspi_stig_rd_cmd(ALT_QSPI_STIG_OPCODE_RDFLGSR, 0, 1, flagsr, 10000);
0108 }
0109
0110
0111
0112 static inline ALT_STATUS_CODE alt_qspi_N25Q_enable(void)
0113 {
0114 ALT_STATUS_CODE status = ALT_E_SUCCESS;
0115
0116
0117
0118 if (status == ALT_E_SUCCESS)
0119 {
0120 status = alt_qspi_stig_cmd(ALT_QSPI_STIG_OPCODE_RESET_EN, 0, 10000);
0121 }
0122
0123 if (status == ALT_E_SUCCESS)
0124 {
0125 status = alt_qspi_stig_cmd(ALT_QSPI_STIG_OPCODE_RESET_MEM, 0, 10000);
0126 }
0127
0128
0129
0130 if (status == ALT_E_SUCCESS)
0131 {
0132 ALT_QSPI_DEV_INST_CONFIG_t cfg =
0133 {
0134 .op_code = ALT_QSPI_STIG_OPCODE_FASTREAD_QUAD_IO,
0135 .inst_type = ALT_QSPI_MODE_SINGLE,
0136 .addr_xfer_type = ALT_QSPI_MODE_QUAD,
0137 .data_xfer_type = ALT_QSPI_MODE_QUAD,
0138 .dummy_cycles = 10
0139 };
0140
0141 status = alt_qspi_device_read_config_set(&cfg);
0142 }
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161 return status;
0162 }
0163
0164 static ALT_STATUS_CODE alt_qspi_N25Q_flag_wait_for_program(uint32_t timeout)
0165 {
0166
0167
0168 if (qspi_device_size < 0x4000000)
0169 {
0170 return ALT_E_SUCCESS;
0171 }
0172
0173 ALT_STATUS_CODE status = ALT_E_SUCCESS;
0174
0175 uint32_t time_out = timeout;
0176 uint32_t stat = 0;
0177 bool infinite = (timeout == ALT_QSPI_TIMEOUT_INFINITE);
0178
0179 do
0180 {
0181 status = alt_qspi_device_status(&stat);
0182 if (status != ALT_E_SUCCESS)
0183 {
0184 break;
0185 }
0186 if (!ALT_QSPI_STIG_SR_BUSY_GET(stat))
0187 {
0188 break;
0189 }
0190 }
0191 while (time_out-- || infinite);
0192
0193 if (time_out == (uint32_t)-1 && !infinite)
0194 {
0195 status = ALT_E_TMO;
0196 }
0197
0198 if (status == ALT_E_SUCCESS)
0199 {
0200 uint32_t flagsr = 0;
0201
0202 do
0203 {
0204 status = alt_qspi_N25Q_device_flag(&flagsr);
0205 if (status != ALT_E_SUCCESS)
0206 {
0207 break;
0208 }
0209 if (ALT_QSPI_STIG_FLAGSR_PROGRAMREADY_GET(flagsr))
0210 {
0211 break;
0212 }
0213 }
0214 while (timeout-- || infinite);
0215
0216 if (timeout == (uint32_t)-1 && !infinite)
0217 {
0218 status = ALT_E_TMO;
0219 }
0220
0221 if (status == ALT_E_SUCCESS)
0222 {
0223 if (ALT_QSPI_STIG_FLAGSR_PROGRAMERROR_GET(flagsr))
0224 {
0225 status = ALT_E_ERROR;
0226 }
0227 }
0228 }
0229 return status;
0230 }
0231
0232 static ALT_STATUS_CODE alt_qspi_N25Q_flag_wait_for_erase(uint32_t timeout)
0233 {
0234
0235
0236 if (qspi_device_size < 0x4000000)
0237 {
0238 return ALT_E_SUCCESS;
0239 }
0240
0241 ALT_STATUS_CODE status = ALT_E_SUCCESS;
0242
0243 uint32_t time_out = timeout;
0244 uint32_t stat = 0;
0245 bool infinite = (timeout == ALT_QSPI_TIMEOUT_INFINITE);
0246
0247 do
0248 {
0249 status = alt_qspi_device_status(&stat);
0250 if (status != ALT_E_SUCCESS)
0251 {
0252 break;
0253 }
0254 if (!ALT_QSPI_STIG_SR_BUSY_GET(stat))
0255 {
0256 break;
0257 }
0258 }
0259 while (time_out-- || infinite);
0260
0261 if (time_out == (uint32_t)-1 && !infinite)
0262 {
0263 status = ALT_E_TMO;
0264 }
0265
0266 if (status == ALT_E_SUCCESS)
0267 {
0268
0269 uint32_t flagsr = 0;
0270
0271 do
0272 {
0273 status = alt_qspi_N25Q_device_flag(&flagsr);
0274 if (status != ALT_E_SUCCESS)
0275 {
0276 break;
0277 }
0278 if (ALT_QSPI_STIG_FLAGSR_ERASEREADY_GET(flagsr))
0279 {
0280 break;
0281 }
0282 }
0283 while (timeout-- || infinite);
0284
0285 if (timeout == (uint32_t)-1 && !infinite)
0286 {
0287 status = ALT_E_TMO;
0288 }
0289
0290 if (status == ALT_E_SUCCESS)
0291 {
0292 if (ALT_QSPI_STIG_FLAGSR_ERASEERROR_GET(flagsr))
0293 {
0294 status = ALT_E_ERROR;
0295 }
0296 }
0297 }
0298
0299 return status;
0300 }
0301 #endif
0302
0303
0304
0305
0306
0307 static inline int alt_qspi_ns_to_multiplier(int ns, int mhz)
0308 {
0309 return ((ns * mhz) + 999) / 1000;
0310 }
0311
0312 ALT_STATUS_CODE alt_qspi_init(void)
0313 {
0314 ALT_STATUS_CODE status = ALT_E_SUCCESS;
0315 alt_freq_t qspi_clk_freq = 0;
0316
0317
0318
0319
0320
0321
0322
0323 if (status == ALT_E_SUCCESS)
0324 {
0325 if (alt_clk_is_enabled(ALT_CLK_QSPI) != ALT_E_TRUE)
0326 {
0327 status = ALT_E_BAD_CLK;
0328 }
0329 }
0330
0331 if (status == ALT_E_SUCCESS)
0332 {
0333 status = alt_clk_freq_get(ALT_CLK_QSPI, &qspi_clk_freq);
0334 if (status == ALT_E_SUCCESS)
0335 {
0336 if (qspi_clk_freq > ALT_QSPI_CLK_FREQ_MAX)
0337 {
0338 return ALT_E_BAD_CLK;
0339 }
0340 }
0341 }
0342
0343 int qspi_clk_mhz = qspi_clk_freq / 1000000;
0344
0345
0346
0347
0348 alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_QSPI_SET_MSK);
0349
0350
0351
0352
0353
0354 if (status == ALT_E_SUCCESS)
0355 {
0356 ALT_QSPI_TIMING_CONFIG_t timing_cfg =
0357 {
0358 .clk_phase = (ALT_QSPI_CLK_PHASE_t)ALT_QSPI_CFG_SELCLKPHASE_RESET,
0359 .clk_pol = (ALT_QSPI_CLK_POLARITY_t)ALT_QSPI_CFG_SELCLKPOL_RESET,
0360 .cs_da = alt_qspi_ns_to_multiplier(ALT_QSPI_TSHSL_NS_DEF, qspi_clk_mhz),
0361 .cs_dads = alt_qspi_ns_to_multiplier(ALT_QSPI_TSD2D_NS_DEF, qspi_clk_mhz),
0362 .cs_eot = alt_qspi_ns_to_multiplier(ALT_QSPI_TCHSH_NS_DEF, qspi_clk_mhz),
0363 .cs_sot = alt_qspi_ns_to_multiplier(ALT_QSPI_TSLCH_NS_DEF, qspi_clk_mhz),
0364 .rd_datacap = 1
0365 };
0366
0367 dprintf("DEBUG[QSPI]: cs_da = %" PRIu32 ".\n", timing_cfg.cs_da);
0368 dprintf("DEBUG[QSPI]: cs_dads = %" PRIu32 ".\n", timing_cfg.cs_dads);
0369 dprintf("DEBUG[QSPI]: cs_eot = %" PRIu32 ".\n", timing_cfg.cs_eot);
0370 dprintf("DEBUG[QSPI]: cs_sot = %" PRIu32 ".\n", timing_cfg.cs_sot);
0371
0372 status = alt_qspi_timing_config_set(&timing_cfg);
0373 }
0374
0375
0376
0377
0378
0379 if (status == ALT_E_SUCCESS)
0380 {
0381 status = alt_qspi_ahb_remap_address_set(0);
0382 }
0383
0384
0385
0386 if (status == ALT_E_SUCCESS)
0387 {
0388 status = alt_qspi_int_disable(ALT_QSPI_INT_STATUS_ALL);
0389 }
0390
0391
0392
0393
0394 if (status == ALT_E_SUCCESS)
0395 {
0396 uint32_t device_sclk_mhz = 54;
0397 uint32_t div_actual = (qspi_clk_mhz + (device_sclk_mhz - 1)) / device_sclk_mhz;
0398 dprintf("DEBUG[QSPI]: div_actual = %" PRIu32 ".\n", div_actual);
0399
0400 ALT_QSPI_BAUD_DIV_t div_bits = (ALT_QSPI_BAUD_DIV_t)(((div_actual + 1) / 2) - 1);
0401 status = alt_qspi_baud_rate_div_set(div_bits);
0402 }
0403
0404 return status;
0405 }
0406
0407 ALT_STATUS_CODE alt_qspi_uninit(void)
0408 {
0409
0410 alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_QSPI_SET_MSK);
0411
0412 return ALT_E_SUCCESS;
0413 }
0414
0415 ALT_STATUS_CODE alt_qspi_disable(void)
0416 {
0417 alt_clrbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_EN_SET_MSK);
0418
0419 return ALT_E_SUCCESS;
0420 }
0421
0422 ALT_STATUS_CODE alt_qspi_enable(void)
0423 {
0424 alt_setbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_EN_SET_MSK);
0425
0426 ALT_STATUS_CODE status = ALT_E_SUCCESS;
0427
0428
0429
0430
0431
0432 #if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT
0433 if (status == ALT_E_SUCCESS)
0434 {
0435 status = alt_qspi_N25Q_enable();
0436 }
0437 #endif
0438
0439 uint32_t rdid = 0;
0440
0441
0442
0443
0444 if (status == ALT_E_SUCCESS)
0445 {
0446 status = alt_qspi_device_rdid(&rdid);
0447 }
0448
0449 if (status == ALT_E_SUCCESS)
0450 {
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470 int cap_code = ALT_QSPI_STIG_RDID_CAPACITYID_GET(rdid);
0471
0472 if ( ((cap_code >> 4) > 0x9) || ((cap_code & 0xf) > 0x9))
0473 {
0474
0475
0476
0477 dprintf("DEBUG[QSPI]: Invalid CapacityID encountered: 0x%02x.\n", cap_code);
0478 status = ALT_E_ERROR;
0479 }
0480 else
0481 {
0482 int cap_decoded = ((cap_code >> 4) * 10) + (cap_code & 0xf);
0483
0484 qspi_device_size = 1 << (cap_decoded + 6);
0485
0486 dprintf("DEBUG[QSPI]: Device size = 0x%" PRIx32 ".\n", qspi_device_size);
0487 }
0488 }
0489
0490
0491
0492 if (status == ALT_E_SUCCESS)
0493 {
0494 ALT_QSPI_DEV_SIZE_CONFIG_t size_cfg =
0495 {
0496 .block_size = ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_RESET,
0497 .page_size = ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_RESET,
0498 .addr_size = ALT_QSPI_DEVSZ_NUMADDRBYTES_RESET,
0499 .lower_wrprot_block = 0,
0500 .upper_wrprot_block = (qspi_device_size - 1) >> 16,
0501 .wrprot_enable = ALT_QSPI_WRPROT_EN_RESET
0502 };
0503
0504 status = alt_qspi_device_size_config_set(&size_cfg);
0505 }
0506
0507
0508
0509
0510
0511
0512
0513 if (status == ALT_E_SUCCESS)
0514 {
0515 status = alt_qspi_dma_config_set(4, 32);
0516 }
0517
0518
0519
0520 return status;
0521 }
0522
0523
0524
0525 uint32_t alt_qspi_int_status_get(void)
0526 {
0527
0528
0529 return alt_read_word(ALT_QSPI_IRQSTAT_ADDR);
0530 }
0531
0532 ALT_STATUS_CODE alt_qspi_int_clear(const uint32_t mask)
0533 {
0534
0535 if ((ALT_QSPI_INT_STATUS_ALL & mask) == 0)
0536 {
0537 return ALT_E_BAD_ARG;
0538 }
0539
0540
0541 alt_write_word(ALT_QSPI_IRQSTAT_ADDR, mask);
0542
0543 return ALT_E_SUCCESS;
0544 }
0545
0546 ALT_STATUS_CODE alt_qspi_int_disable(const uint32_t mask)
0547 {
0548 if (alt_qspi_is_idle() == false)
0549 {
0550 return ALT_E_ERROR;
0551 }
0552
0553
0554 if ((ALT_QSPI_INT_STATUS_ALL & mask) == 0)
0555 {
0556 return ALT_E_BAD_ARG;
0557 }
0558
0559
0560 alt_clrbits_word(ALT_QSPI_IRQMSK_ADDR, mask);
0561
0562 return ALT_E_SUCCESS;
0563 }
0564
0565 ALT_STATUS_CODE alt_qspi_int_enable(const uint32_t mask)
0566 {
0567 if (alt_qspi_is_idle() == false)
0568 {
0569 return ALT_E_ERROR;
0570 }
0571
0572
0573 if ((ALT_QSPI_INT_STATUS_ALL & mask) == 0)
0574 {
0575 return ALT_E_BAD_ARG;
0576 }
0577
0578
0579 alt_setbits_word(ALT_QSPI_IRQMSK_ADDR, mask);
0580
0581 return ALT_E_SUCCESS;
0582 }
0583
0584
0585
0586 bool alt_qspi_is_idle(void)
0587 {
0588
0589
0590 return ALT_QSPI_CFG_IDLE_GET(alt_read_word(ALT_QSPI_CFG_ADDR)) == 1;
0591 }
0592
0593
0594
0595 static ALT_STATUS_CODE alt_qspi_indirect_write_start_bank(uint32_t dst, size_t length);
0596
0597 static ALT_STATUS_CODE alt_qspi_indirect_page_bound_write_helper(uint32_t dst, const char * src, size_t length)
0598 {
0599 ALT_STATUS_CODE status = ALT_E_SUCCESS;
0600
0601 if (status == ALT_E_SUCCESS)
0602 {
0603 status = alt_qspi_indirect_write_start_bank(dst, length);
0604 }
0605
0606 if (status == ALT_E_SUCCESS)
0607 {
0608 uint32_t write_count = 0;
0609 uint32_t write_capacity = ALT_QSPI_SRAM_FIFO_ENTRY_COUNT - alt_qspi_sram_partition_get();
0610
0611 while (write_count < length)
0612 {
0613 uint32_t space = write_capacity - alt_qspi_indirect_write_fill_level();
0614 space = MIN(space, (length - write_count)/ sizeof(uint32_t));
0615
0616 const uint32_t * data = (const uint32_t *)(src + write_count);
0617 for (uint32_t i = 0; i < space; ++i)
0618 {
0619 alt_write_word(ALT_QSPIDATA_ADDR, *data++);
0620 }
0621
0622 write_count += space * sizeof(uint32_t);
0623 }
0624 }
0625
0626 if (status == ALT_E_SUCCESS)
0627 {
0628 status = alt_qspi_indirect_write_finish();
0629 }
0630
0631 return status;
0632 }
0633
0634 static ALT_STATUS_CODE alt_qspi_indirect_subsector_aligned_write_helper(const char * data, uint32_t subsec_addr)
0635 {
0636 ALT_STATUS_CODE status = ALT_E_SUCCESS;
0637
0638 for (int i = 0; i < ALT_QSPI_SUBSECTOR_SIZE / ALT_QSPI_PAGE_SIZE; i++)
0639 {
0640 int offset = i * ALT_QSPI_PAGE_SIZE;
0641
0642 status = alt_qspi_indirect_page_bound_write_helper(subsec_addr + offset, data + offset, ALT_QSPI_PAGE_SIZE);
0643 if (status != ALT_E_SUCCESS)
0644 {
0645 break;
0646 }
0647 }
0648
0649 return status;
0650 }
0651
0652 static ALT_STATUS_CODE alt_qspi_indirect_read_start_bank(uint32_t src, size_t size);
0653
0654
0655
0656
0657
0658 static ALT_STATUS_CODE alt_qspi_read_bank(char * dst, uint32_t src, size_t size)
0659 {
0660 ALT_STATUS_CODE status = ALT_E_SUCCESS;
0661
0662 if (status == ALT_E_SUCCESS)
0663 {
0664 status = alt_qspi_indirect_read_start_bank(src, size);
0665 }
0666
0667 if (status == ALT_E_SUCCESS)
0668 {
0669 uint32_t read_count = 0;
0670
0671 while (!alt_qspi_indirect_read_is_complete())
0672 {
0673 uint32_t level = alt_qspi_indirect_read_fill_level();
0674
0675
0676 uint32_t * data = (uint32_t *)(dst + read_count);
0677 for (uint32_t i = 0; i < level; ++i)
0678 {
0679 *data++ = alt_read_word(ALT_QSPIDATA_ADDR);
0680 }
0681
0682 read_count += level * sizeof(uint32_t);
0683 }
0684 }
0685
0686 if (status == ALT_E_SUCCESS)
0687 {
0688 status = alt_qspi_indirect_read_finish();
0689 }
0690
0691 return status;
0692 }
0693
0694 ALT_STATUS_CODE alt_qspi_read(void * dst, uint32_t src, size_t size)
0695 {
0696 if (src >= qspi_device_size)
0697 {
0698 return ALT_E_ERROR;
0699 }
0700
0701 if (src + size - 1 >= qspi_device_size)
0702 {
0703 return ALT_E_ERROR;
0704 }
0705
0706 if (size == 0)
0707 {
0708 return ALT_E_SUCCESS;
0709 }
0710
0711 if ((uintptr_t)dst & 0x3)
0712 {
0713 return ALT_E_ERROR;
0714 }
0715
0716 if (src & 0x3)
0717 {
0718 return ALT_E_ERROR;
0719 }
0720
0721 if (size & 0x3)
0722 {
0723 return ALT_E_ERROR;
0724 }
0725
0726
0727
0728
0729 if (ALT_QSPI_INDRD_RD_STAT_GET(alt_read_word(ALT_QSPI_INDRD_ADDR)))
0730 {
0731 return ALT_E_ERROR;
0732 }
0733
0734
0735
0736 ALT_STATUS_CODE status = ALT_E_SUCCESS;
0737
0738
0739
0740
0741
0742
0743 uint32_t bank_count = ((src + size - 1) >> 24) - (src >> 24) + 1;
0744 uint32_t bank_addr = src & ALT_QSPI_BANK_ADDR_MSK;
0745 uint32_t bank_ofst = src & (ALT_QSPI_BANK_SIZE - 1);
0746
0747 char * data = (char *)dst;
0748
0749 uint32_t copy_length = MIN(size, ALT_QSPI_BANK_SIZE - bank_ofst);
0750
0751 dprintf("DEBUG[QSPI]: read(): bulk: mem_addr = %p; flash_addr = 0x%" PRIx32 ".\n", data, src);
0752 dprintf("DEBUG[QSPI]: read(): bulk: bank_count = 0x%" PRIx32 ", bank_ofst = 0x%" PRIx32 ".\n", bank_count, bank_ofst);
0753
0754 for (uint32_t i = 0; i < bank_count; ++i)
0755 {
0756 dprintf("DEBUG[QSPI]: read(): bank 0x%" PRIx32 "; copy_length = 0x%" PRIx32 ".\n", bank_addr >> 24, copy_length);
0757
0758 status = alt_qspi_device_bank_select(bank_addr >> 24);
0759 if (status != ALT_E_SUCCESS)
0760 {
0761 break;
0762 }
0763
0764 status = alt_qspi_read_bank(dst, bank_ofst, copy_length);
0765 if (status != ALT_E_SUCCESS)
0766 {
0767 break;
0768 }
0769
0770 bank_addr += ALT_QSPI_BANK_SIZE;
0771 data += copy_length;
0772 size -= copy_length;
0773
0774 copy_length = MIN(size, ALT_QSPI_BANK_SIZE);
0775 }
0776
0777 return status;
0778 }
0779
0780 static ALT_STATUS_CODE alt_qspi_write_bank(uint32_t dst, const char * src, size_t size)
0781 {
0782 ALT_STATUS_CODE status = ALT_E_SUCCESS;
0783
0784
0785
0786 uint32_t page_ofst = dst & (ALT_QSPI_PAGE_SIZE - 1);
0787 uint32_t write_size = MIN(size, ALT_QSPI_PAGE_SIZE - page_ofst);
0788
0789 while (size)
0790 {
0791 dprintf("DEBUG[QSPI]: write(): flash dst = 0x%" PRIx32 ", mem src = %p, write size = 0x%" PRIx32 ", size left = 0x%x.\n", dst, src, write_size, size);
0792
0793 status = alt_qspi_indirect_page_bound_write_helper(dst, src, write_size);
0794 if (status != ALT_E_SUCCESS)
0795 {
0796 break;
0797 }
0798
0799 dst += write_size;
0800 src += write_size;
0801 size -= write_size;
0802
0803 write_size = MIN(size, ALT_QSPI_PAGE_SIZE);
0804 }
0805
0806 return status;
0807 }
0808
0809 ALT_STATUS_CODE alt_qspi_write(uint32_t dst, const void * src, size_t size)
0810 {
0811 if (dst >= qspi_device_size)
0812 {
0813 return ALT_E_ERROR;
0814 }
0815
0816 if (dst + size - 1 >= qspi_device_size)
0817 {
0818 return ALT_E_ERROR;
0819 }
0820
0821 if (size == 0)
0822 {
0823 return ALT_E_SUCCESS;
0824 }
0825
0826 if ((uintptr_t)src & 0x3)
0827 {
0828 return ALT_E_ERROR;
0829 }
0830
0831 if (dst & 0x3)
0832 {
0833 return ALT_E_ERROR;
0834 }
0835
0836 if (size & 0x3)
0837 {
0838 return ALT_E_ERROR;
0839 }
0840
0841
0842
0843
0844 if (ALT_QSPI_INDWR_RDSTAT_GET(alt_read_word(ALT_QSPI_INDWR_ADDR)))
0845 {
0846 return ALT_E_ERROR;
0847 }
0848
0849
0850
0851 ALT_STATUS_CODE status = ALT_E_SUCCESS;
0852
0853 uint32_t bank_count = ((dst + size - 1) >> 24) - (dst >> 24) + 1;
0854 uint32_t bank_addr = dst & ALT_QSPI_BANK_ADDR_MSK;
0855 uint32_t bank_ofst = dst & (ALT_QSPI_BANK_SIZE - 1);
0856
0857 const char * data = src;
0858
0859 uint32_t copy_length = MIN(size, ALT_QSPI_BANK_SIZE - bank_ofst);
0860
0861 dprintf("DEBUG[QSPI]: write(): bulk: flash_addr = 0x%" PRIx32 "; mem_addr = %p.\n", dst, data);
0862 dprintf("DEBUG[QSPI]: write(): bulk: bank_count = 0x%" PRIx32 ", bank_ofst = 0x%" PRIx32 ".\n", bank_count, bank_ofst);
0863
0864 for (uint32_t i = 0; i < bank_count; ++i)
0865 {
0866 dprintf("DEBUG[QSPI]: write(): bank 0x%" PRIx32 "; copy_length = 0x%" PRIx32 ".\n", bank_addr >> 24, copy_length);
0867
0868 status = alt_qspi_device_bank_select(bank_addr >> 24);
0869 if (status != ALT_E_SUCCESS)
0870 {
0871 break;
0872 }
0873
0874 status = alt_qspi_write_bank(bank_ofst, data, copy_length);
0875 if (status != ALT_E_SUCCESS)
0876 {
0877 break;
0878 }
0879
0880 bank_addr += ALT_QSPI_BANK_SIZE;
0881 data += copy_length;
0882 size -= copy_length;
0883
0884 copy_length = MIN(size, ALT_QSPI_BANK_SIZE);
0885 }
0886
0887 return status;
0888 }
0889
0890 static ALT_STATUS_CODE alt_qspi_erase_subsector_bank(uint32_t addr);
0891
0892 static ALT_STATUS_CODE alt_qspi_replace_bank(uint32_t dst, const char * src, size_t size)
0893 {
0894 ALT_STATUS_CODE status = ALT_E_SUCCESS;
0895
0896
0897
0898
0899
0900
0901
0902
0903
0904
0905
0906
0907
0908
0909
0910
0911
0912
0913 uint32_t subsec_count = ((dst + size - 1) >> 12) - (dst >> 12) + 1;
0914 uint32_t subsec_addr = dst & ALT_QSPI_SUBSECTOR_ADDR_MSK;
0915
0916 uint32_t subsec_partial_head = MIN(ALT_QSPI_SUBSECTOR_SIZE - (dst & (ALT_QSPI_SUBSECTOR_SIZE - 1)), size) & (ALT_QSPI_SUBSECTOR_SIZE - 1);
0917 uint32_t subsec_partial_tail = (size - subsec_partial_head) & (ALT_QSPI_SUBSECTOR_SIZE - 1);
0918
0919 dprintf("DEBUG[QSPI]: replace(): report: dst = 0x%" PRIx32 "; size = 0x%x.\n",
0920 dst, size);
0921 dprintf("DEBUG[QSPI]: replace(): report: subsec_count = 0x%" PRIx32 "; subsec_addr = 0x%" PRIx32 ".\n",
0922 subsec_count, subsec_addr);
0923 dprintf("DEBUG[QSPI]: replace(): report: partial_head = 0x%" PRIx32 "; partial_tail = 0x%" PRIx32 ".\n",
0924 subsec_partial_head, subsec_partial_tail);
0925
0926
0927
0928 if (subsec_partial_head)
0929 {
0930
0931
0932
0933
0934 char subsec_buf[ALT_QSPI_SUBSECTOR_SIZE];
0935
0936 uint32_t subsec_ofst = dst & ~ALT_QSPI_SUBSECTOR_ADDR_MSK;
0937
0938
0939
0940
0941
0942
0943 if (status == ALT_E_SUCCESS)
0944 {
0945 status = alt_qspi_read_bank(subsec_buf, subsec_addr, subsec_ofst);
0946 }
0947 if (status == ALT_E_SUCCESS)
0948 {
0949 status = alt_qspi_erase_subsector_bank(subsec_addr);
0950 }
0951 if (status == ALT_E_SUCCESS)
0952 {
0953 memcpy(subsec_buf + subsec_ofst, src, subsec_partial_head);
0954 status = alt_qspi_indirect_subsector_aligned_write_helper(subsec_buf, subsec_addr);
0955 }
0956
0957
0958 src += subsec_partial_head;
0959 size -= subsec_partial_head;
0960
0961
0962 subsec_count--;
0963 subsec_addr += ALT_QSPI_SUBSECTOR_SIZE;
0964
0965 dprintf("DEBUG[QSPI]: replace(): partial head: subsec_ofst = 0x%" PRIx32 "; size left = 0x%x; status = %" PRIi32 ".\n",
0966 subsec_ofst, size, status);
0967 }
0968
0969
0970
0971
0972
0973 if (subsec_partial_tail)
0974 {
0975 subsec_count--;
0976 }
0977
0978
0979
0980 for (uint32_t i = 0; i < subsec_count; ++i)
0981 {
0982
0983
0984
0985 if (status == ALT_E_SUCCESS)
0986 {
0987 status = alt_qspi_erase_subsector_bank(subsec_addr);
0988 }
0989 if (status == ALT_E_SUCCESS)
0990 {
0991 status = alt_qspi_indirect_subsector_aligned_write_helper(src, subsec_addr);
0992 }
0993
0994 src += ALT_QSPI_SUBSECTOR_SIZE;
0995 size -= ALT_QSPI_SUBSECTOR_SIZE;
0996
0997
0998 subsec_addr += ALT_QSPI_SUBSECTOR_SIZE;
0999
1000 dprintf("DEBUG[QSPI]: replace(): subsec aligned: size left = 0x%x, status = %" PRIi32 ".\n",
1001 size, status);
1002 }
1003
1004
1005
1006 if (subsec_partial_tail)
1007 {
1008
1009
1010
1011
1012 char subsec_buf[ALT_QSPI_SUBSECTOR_SIZE];
1013
1014
1015
1016
1017
1018
1019 if (status == ALT_E_SUCCESS)
1020 {
1021 status = alt_qspi_read_bank(subsec_buf + subsec_partial_tail,
1022 subsec_addr + subsec_partial_tail,
1023 ALT_QSPI_SUBSECTOR_SIZE - subsec_partial_tail);
1024 }
1025 if (status == ALT_E_SUCCESS)
1026 {
1027 status = alt_qspi_erase_subsector_bank(subsec_addr);
1028 }
1029 if (status == ALT_E_SUCCESS)
1030 {
1031 memcpy(subsec_buf, src, subsec_partial_tail);
1032 status = alt_qspi_indirect_subsector_aligned_write_helper(subsec_buf, subsec_addr);
1033 }
1034
1035 src += subsec_partial_tail;
1036 size -= subsec_partial_tail;
1037
1038 dprintf("DEBUG[QSPI]: replace(): partial tail: size left = 0x%x, status = %" PRIi32 ".\n",
1039 size, status);
1040 }
1041
1042 return status;
1043 }
1044
1045 ALT_STATUS_CODE alt_qspi_replace(uint32_t dst, const void * src, size_t size)
1046 {
1047 if (dst >= qspi_device_size)
1048 {
1049 return ALT_E_ERROR;
1050 }
1051
1052 if (dst + size - 1 >= qspi_device_size)
1053 {
1054 return ALT_E_ERROR;
1055 }
1056
1057 if (size == 0)
1058 {
1059 return ALT_E_SUCCESS;
1060 }
1061
1062 if ((uintptr_t)src & 0x3)
1063 {
1064 return ALT_E_ERROR;
1065 }
1066
1067 if (dst & 0x3)
1068 {
1069 return ALT_E_ERROR;
1070 }
1071
1072 if (size & 0x3)
1073 {
1074 return ALT_E_ERROR;
1075 }
1076
1077
1078
1079
1080 if (ALT_QSPI_INDRD_RD_STAT_GET(alt_read_word(ALT_QSPI_INDRD_ADDR)))
1081 {
1082 return ALT_E_ERROR;
1083 }
1084
1085
1086 if (ALT_QSPI_INDWR_RDSTAT_GET(alt_read_word(ALT_QSPI_INDWR_ADDR)))
1087 {
1088 return ALT_E_ERROR;
1089 }
1090
1091
1092
1093 ALT_STATUS_CODE status = ALT_E_SUCCESS;
1094
1095 uint32_t bank_count = ((dst + size - 1) >> 24) - (dst >> 24) + 1;
1096 uint32_t bank_addr = dst & ALT_QSPI_BANK_ADDR_MSK;
1097 uint32_t bank_ofst = dst & (ALT_QSPI_BANK_SIZE - 1);
1098
1099 const char * data = (const char *)src;
1100
1101 uint32_t copy_length = MIN(size, ALT_QSPI_BANK_SIZE - bank_ofst);
1102
1103 dprintf("DEBUG[QSPI]: replace(): bulk: flash_addr = 0x%" PRIx32 "; mem_addr = %p.\n", dst, data);
1104 dprintf("DEBUG[QSPI]: replace(): bulk: bank_count = 0x%" PRIx32 ", bank_ofst = 0x%" PRIx32 ".\n", bank_count, bank_ofst);
1105
1106 for (uint32_t i = 0; i < bank_count; ++i)
1107 {
1108 dprintf("DEBUG[QSPI]: replace(): bank 0x%" PRIx32 "; copy_length = 0x%" PRIx32 ".\n", bank_addr >> 24, copy_length);
1109
1110 status = alt_qspi_device_bank_select(bank_addr >> 24);
1111 if (status != ALT_E_SUCCESS)
1112 {
1113 break;
1114 }
1115
1116 status = alt_qspi_replace_bank(bank_ofst, data, copy_length);
1117 if (status != ALT_E_SUCCESS)
1118 {
1119 break;
1120 }
1121
1122 bank_addr += ALT_QSPI_BANK_SIZE;
1123 data += copy_length;
1124 size -= copy_length;
1125
1126 copy_length = MIN(size, ALT_QSPI_BANK_SIZE);
1127 }
1128
1129 return status;
1130 }
1131
1132
1133
1134 ALT_QSPI_BAUD_DIV_t alt_qspi_baud_rate_div_get(void)
1135 {
1136 uint32_t baud_rate_div = ALT_QSPI_CFG_BAUDDIV_GET(alt_read_word(ALT_QSPI_CFG_ADDR));
1137 return (ALT_QSPI_BAUD_DIV_t) baud_rate_div;
1138 }
1139
1140 ALT_STATUS_CODE alt_qspi_baud_rate_div_set(const ALT_QSPI_BAUD_DIV_t baud_rate_div)
1141 {
1142 if (0xf < (uint32_t)baud_rate_div)
1143 {
1144
1145 return ALT_E_BAD_ARG;
1146 }
1147
1148
1149 alt_replbits_word(ALT_QSPI_CFG_ADDR,
1150 ALT_QSPI_CFG_BAUDDIV_SET_MSK,
1151 ALT_QSPI_CFG_BAUDDIV_SET(baud_rate_div));
1152
1153 return ALT_E_SUCCESS;
1154 }
1155
1156 ALT_STATUS_CODE alt_qspi_chip_select_config_get(uint32_t* cs,
1157 ALT_QSPI_CS_MODE_t* cs_mode)
1158 {
1159 uint32_t cfg = alt_read_word(ALT_QSPI_CFG_ADDR);
1160
1161 *cs = ALT_QSPI_CFG_PERCSLINES_GET(cfg);
1162 *cs_mode = (ALT_QSPI_CS_MODE_t) ALT_QSPI_CFG_PERSELDEC_GET(cfg);
1163
1164 return ALT_E_SUCCESS;
1165 }
1166
1167 ALT_STATUS_CODE alt_qspi_chip_select_config_set(const uint32_t cs,
1168 const ALT_QSPI_CS_MODE_t cs_mode)
1169 {
1170
1171
1172
1173
1174
1175
1176 if (cs > ((1 << ALT_QSPI_CFG_PERCSLINES_WIDTH) - 1))
1177 {
1178
1179 return ALT_E_ARG_RANGE;
1180 }
1181
1182 if ((cs_mode != ALT_QSPI_CS_MODE_SINGLE_SELECT) && (cs_mode != ALT_QSPI_CS_MODE_DECODE))
1183 {
1184 return ALT_E_INV_OPTION;
1185 }
1186
1187
1188
1189
1190 uint32_t cfg = alt_read_word(ALT_QSPI_CFG_ADDR);
1191 cfg &= ALT_QSPI_CFG_PERCSLINES_CLR_MSK & ALT_QSPI_CFG_PERSELDEC_CLR_MSK;
1192 cfg |= ALT_QSPI_CFG_PERCSLINES_SET(cs) | ALT_QSPI_CFG_PERSELDEC_SET(cs_mode);
1193 alt_write_word(ALT_QSPI_CFG_ADDR, cfg);
1194
1195 return ALT_E_SUCCESS;
1196 }
1197
1198 ALT_STATUS_CODE alt_qspi_mode_bit_disable(void)
1199 {
1200
1201
1202 alt_clrbits_word(ALT_QSPI_DEVRD_ADDR, ALT_QSPI_DEVRD_ENMODBITS_SET_MSK);
1203
1204 return ALT_E_SUCCESS;
1205 }
1206
1207 ALT_STATUS_CODE alt_qspi_mode_bit_enable(void)
1208 {
1209
1210
1211 alt_setbits_word(ALT_QSPI_DEVRD_ADDR, ALT_QSPI_DEVRD_ENMODBITS_SET_MSK);
1212
1213 return ALT_E_SUCCESS;
1214 }
1215
1216 uint32_t alt_qspi_mode_bit_config_get(void)
1217 {
1218
1219
1220 return ALT_QSPI_MODBIT_MOD_GET(alt_read_word(ALT_QSPI_MODBIT_ADDR));
1221 }
1222
1223 ALT_STATUS_CODE alt_qspi_mode_bit_config_set(const uint32_t mode_bits)
1224 {
1225 if (alt_qspi_is_idle() == false)
1226 {
1227 return ALT_E_ERROR;
1228 }
1229
1230 if (mode_bits > ((1 << ALT_QSPI_MODBIT_MOD_WIDTH) - 1))
1231 {
1232
1233 return ALT_E_ARG_RANGE;
1234 }
1235
1236
1237
1238 alt_replbits_word(ALT_QSPI_MODBIT_ADDR,
1239 ALT_QSPI_MODBIT_MOD_SET_MSK,
1240 ALT_QSPI_MODBIT_MOD_SET(mode_bits));
1241
1242 return ALT_E_SUCCESS;
1243 }
1244
1245 ALT_STATUS_CODE alt_qspi_device_size_config_get(ALT_QSPI_DEV_SIZE_CONFIG_t * cfg)
1246 {
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258 uint32_t devsz = alt_read_word(ALT_QSPI_DEVSZ_ADDR);
1259
1260 cfg->block_size = ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_GET(devsz);
1261 cfg->page_size = ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_GET(devsz);
1262 cfg->addr_size = ALT_QSPI_DEVSZ_NUMADDRBYTES_GET(devsz);
1263
1264
1265
1266
1267 cfg->lower_wrprot_block = ALT_QSPI_LOWWRPROT_SUBSECTOR_GET(alt_read_word(ALT_QSPI_LOWWRPROT_ADDR));
1268 cfg->upper_wrprot_block = ALT_QSPI_UPPWRPROT_SUBSECTOR_GET(alt_read_word(ALT_QSPI_UPPWRPROT_ADDR));
1269 cfg->wrprot_enable = ALT_QSPI_WRPROT_EN_GET(alt_read_word(ALT_QSPI_WRPROT_ADDR));
1270
1271 return ALT_E_SUCCESS;
1272 }
1273
1274 ALT_STATUS_CODE alt_qspi_device_size_config_set(const ALT_QSPI_DEV_SIZE_CONFIG_t * cfg)
1275 {
1276 if (cfg->block_size > ((1 << ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_WIDTH) - 1))
1277 {
1278 return ALT_E_ARG_RANGE;
1279 }
1280
1281 if (cfg->page_size > ((1 << ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_WIDTH) - 1))
1282 {
1283 return ALT_E_ARG_RANGE;
1284 }
1285
1286 if (cfg->addr_size > ((1 << ALT_QSPI_DEVSZ_NUMADDRBYTES_WIDTH) - 1))
1287 {
1288 return ALT_E_ARG_RANGE;
1289 }
1290
1291 if (cfg->lower_wrprot_block > cfg->upper_wrprot_block)
1292 {
1293
1294 return ALT_E_ARG_RANGE;
1295 }
1296
1297
1298
1299 uint32_t value = ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_SET(cfg->block_size) |
1300 ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_SET(cfg->page_size) |
1301 ALT_QSPI_DEVSZ_NUMADDRBYTES_SET(cfg->addr_size);
1302
1303 alt_write_word(ALT_QSPI_DEVSZ_ADDR, value);
1304
1305 if (cfg->wrprot_enable)
1306 {
1307 alt_write_word(ALT_QSPI_LOWWRPROT_ADDR, cfg->lower_wrprot_block);
1308 alt_write_word(ALT_QSPI_UPPWRPROT_ADDR, cfg->upper_wrprot_block);
1309 }
1310
1311
1312
1313
1314 if (cfg->wrprot_enable)
1315 {
1316 alt_setbits_word(ALT_QSPI_WRPROT_ADDR, ALT_QSPI_WRPROT_EN_SET(1));
1317 }
1318 else
1319 {
1320 alt_clrbits_word(ALT_QSPI_WRPROT_ADDR, ALT_QSPI_WRPROT_EN_SET(1));
1321 }
1322 return ALT_E_SUCCESS;
1323 }
1324
1325 ALT_STATUS_CODE alt_qspi_device_read_config_get(ALT_QSPI_DEV_INST_CONFIG_t * cfg)
1326 {
1327
1328 uint32_t devrd = alt_read_word(ALT_QSPI_DEVRD_ADDR);
1329
1330 cfg->op_code = ALT_QSPI_DEVRD_RDOPCODE_GET(devrd);
1331 cfg->inst_type = (ALT_QSPI_MODE_t) ALT_QSPI_DEVRD_INSTWIDTH_GET(devrd);
1332 cfg->addr_xfer_type = (ALT_QSPI_MODE_t) ALT_QSPI_DEVRD_ADDRWIDTH_GET(devrd);
1333 cfg->data_xfer_type = (ALT_QSPI_MODE_t) ALT_QSPI_DEVRD_DATAWIDTH_GET(devrd);
1334 cfg->dummy_cycles = ALT_QSPI_DEVRD_DUMMYRDCLKS_GET(devrd);
1335
1336 return ALT_E_SUCCESS;
1337 }
1338
1339 ALT_STATUS_CODE alt_qspi_device_read_config_set(const ALT_QSPI_DEV_INST_CONFIG_t * cfg)
1340 {
1341 if (alt_qspi_is_idle() == false)
1342 {
1343 return ALT_E_ERROR;
1344 }
1345
1346
1347
1348 if (cfg->op_code > ((1 << ALT_QSPI_DEVRD_RDOPCODE_WIDTH) - 1))
1349 {
1350 return ALT_E_BAD_ARG;
1351 }
1352
1353 switch (cfg->inst_type)
1354 {
1355 case ALT_QSPI_MODE_SINGLE:
1356 case ALT_QSPI_MODE_DUAL:
1357 case ALT_QSPI_MODE_QUAD:
1358 break;
1359 default:
1360 return ALT_E_BAD_ARG;
1361 }
1362
1363 switch (cfg->addr_xfer_type)
1364 {
1365 case ALT_QSPI_MODE_SINGLE:
1366 case ALT_QSPI_MODE_DUAL:
1367 case ALT_QSPI_MODE_QUAD:
1368 break;
1369 default:
1370 return ALT_E_BAD_ARG;
1371 }
1372
1373 switch (cfg->data_xfer_type)
1374 {
1375 case ALT_QSPI_MODE_SINGLE:
1376 case ALT_QSPI_MODE_DUAL:
1377 case ALT_QSPI_MODE_QUAD:
1378 break;
1379 default:
1380 return ALT_E_BAD_ARG;
1381 }
1382
1383 if (cfg->dummy_cycles > ((1 << ALT_QSPI_DEVRD_DUMMYRDCLKS_WIDTH) - 1))
1384 {
1385 return ALT_E_BAD_ARG;
1386 }
1387
1388
1389
1390
1391 uint32_t devrd = alt_read_word(ALT_QSPI_DEVRD_ADDR);
1392
1393 devrd &= ALT_QSPI_DEVRD_RDOPCODE_CLR_MSK &
1394 ALT_QSPI_DEVRD_INSTWIDTH_CLR_MSK &
1395 ALT_QSPI_DEVRD_ADDRWIDTH_CLR_MSK &
1396 ALT_QSPI_DEVRD_DATAWIDTH_CLR_MSK &
1397 ALT_QSPI_DEVRD_DUMMYRDCLKS_CLR_MSK;
1398
1399 devrd |= ALT_QSPI_DEVRD_RDOPCODE_SET(cfg->op_code) |
1400 ALT_QSPI_DEVRD_INSTWIDTH_SET(cfg->inst_type) |
1401 ALT_QSPI_DEVRD_ADDRWIDTH_SET(cfg->addr_xfer_type) |
1402 ALT_QSPI_DEVRD_DATAWIDTH_SET(cfg->data_xfer_type) |
1403 ALT_QSPI_DEVRD_DUMMYRDCLKS_SET(cfg->dummy_cycles);
1404
1405 alt_write_word(ALT_QSPI_DEVRD_ADDR, devrd);
1406
1407 return ALT_E_SUCCESS;
1408 }
1409
1410 ALT_STATUS_CODE alt_qspi_device_write_config_get(ALT_QSPI_DEV_INST_CONFIG_t * cfg)
1411 {
1412
1413 uint32_t devwr = alt_read_word(ALT_QSPI_DEVWR_ADDR);
1414
1415 cfg->op_code = ALT_QSPI_DEVWR_WROPCODE_GET(devwr);
1416
1417
1418
1419 cfg->inst_type = (ALT_QSPI_MODE_t) ALT_QSPI_DEVRD_INSTWIDTH_GET(alt_read_word(ALT_QSPI_DEVRD_ADDR));
1420 cfg->addr_xfer_type = (ALT_QSPI_MODE_t) ALT_QSPI_DEVWR_ADDRWIDTH_GET(devwr);
1421 cfg->data_xfer_type = (ALT_QSPI_MODE_t) ALT_QSPI_DEVWR_DATAWIDTH_GET(devwr);
1422 cfg->dummy_cycles = ALT_QSPI_DEVWR_DUMMYWRCLKS_GET(devwr);
1423
1424 return ALT_E_SUCCESS;
1425 }
1426
1427 ALT_STATUS_CODE alt_qspi_device_write_config_set(const ALT_QSPI_DEV_INST_CONFIG_t * cfg)
1428 {
1429 if (alt_qspi_is_idle() == false)
1430 {
1431 return ALT_E_ERROR;
1432 }
1433
1434
1435
1436 if (cfg->op_code > ((1 << ALT_QSPI_DEVWR_WROPCODE_WIDTH) - 1))
1437 {
1438 return ALT_E_BAD_ARG;
1439 }
1440
1441 switch (cfg->inst_type)
1442 {
1443 case ALT_QSPI_MODE_SINGLE:
1444 case ALT_QSPI_MODE_DUAL:
1445 case ALT_QSPI_MODE_QUAD:
1446 break;
1447 default:
1448 return ALT_E_BAD_ARG;
1449 }
1450
1451 switch (cfg->addr_xfer_type)
1452 {
1453 case ALT_QSPI_MODE_SINGLE:
1454 case ALT_QSPI_MODE_DUAL:
1455 case ALT_QSPI_MODE_QUAD:
1456 break;
1457 default:
1458 return ALT_E_BAD_ARG;
1459 }
1460
1461 switch (cfg->data_xfer_type)
1462 {
1463 case ALT_QSPI_MODE_SINGLE:
1464 case ALT_QSPI_MODE_DUAL:
1465 case ALT_QSPI_MODE_QUAD:
1466 break;
1467 default:
1468 return ALT_E_BAD_ARG;
1469 }
1470
1471 if (cfg->dummy_cycles > ((1 << ALT_QSPI_DEVWR_DUMMYWRCLKS_WIDTH) - 1))
1472 {
1473 return ALT_E_BAD_ARG;
1474 }
1475
1476
1477
1478
1479 uint32_t devwr = alt_read_word(ALT_QSPI_DEVWR_ADDR);
1480
1481 devwr &= ALT_QSPI_DEVWR_WROPCODE_CLR_MSK &
1482 ALT_QSPI_DEVWR_ADDRWIDTH_CLR_MSK &
1483 ALT_QSPI_DEVWR_DATAWIDTH_CLR_MSK &
1484 ALT_QSPI_DEVWR_DUMMYWRCLKS_CLR_MSK;
1485
1486 devwr |= ALT_QSPI_DEVWR_WROPCODE_SET(cfg->op_code) |
1487 ALT_QSPI_DEVWR_ADDRWIDTH_SET(cfg->addr_xfer_type) |
1488 ALT_QSPI_DEVWR_DATAWIDTH_SET(cfg->data_xfer_type) |
1489 ALT_QSPI_DEVWR_DUMMYWRCLKS_SET(cfg->dummy_cycles);
1490
1491 alt_write_word(ALT_QSPI_DEVWR_ADDR, devwr);
1492
1493
1494
1495
1496
1497 alt_replbits_word(ALT_QSPI_DEVRD_ADDR,
1498 ALT_QSPI_DEVRD_INSTWIDTH_SET_MSK,
1499 ALT_QSPI_DEVRD_INSTWIDTH_SET((uint32_t) cfg->inst_type));
1500
1501 return ALT_E_SUCCESS;
1502 }
1503
1504 ALT_STATUS_CODE alt_qspi_timing_config_get(ALT_QSPI_TIMING_CONFIG_t * cfg)
1505 {
1506
1507 uint32_t cfgreg = alt_read_word(ALT_QSPI_CFG_ADDR);
1508 cfg->clk_phase = (ALT_QSPI_CLK_PHASE_t) ALT_QSPI_CFG_SELCLKPHASE_GET(cfgreg);
1509 cfg->clk_pol = (ALT_QSPI_CLK_POLARITY_t) ALT_QSPI_CFG_SELCLKPOL_GET(cfgreg);
1510
1511
1512 uint32_t delayreg = alt_read_word(ALT_QSPI_DELAY_ADDR);
1513 cfg->cs_sot = ALT_QSPI_DELAY_INIT_GET(delayreg);
1514 cfg->cs_eot = ALT_QSPI_DELAY_AFTER_GET(delayreg);
1515 cfg->cs_dads = ALT_QSPI_DELAY_BTWN_GET(delayreg);
1516 cfg->cs_da = ALT_QSPI_DELAY_NSS_GET(delayreg);
1517
1518
1519 cfg->rd_datacap = ALT_QSPI_RDDATACAP_DELAY_GET(alt_read_word(ALT_QSPI_RDDATACAP_ADDR));
1520
1521 return ALT_E_SUCCESS;
1522 }
1523
1524 ALT_STATUS_CODE alt_qspi_timing_config_set(const ALT_QSPI_TIMING_CONFIG_t * cfg)
1525 {
1526 if (alt_qspi_is_idle() == false)
1527 {
1528 return ALT_E_ERROR;
1529 }
1530
1531
1532
1533 switch (cfg->clk_phase)
1534 {
1535 case ALT_QSPI_CLK_PHASE_ACTIVE:
1536 case ALT_QSPI_CLK_PHASE_INACTIVE:
1537 break;
1538 default:
1539 return ALT_E_BAD_ARG;
1540 }
1541
1542 switch (cfg->clk_pol)
1543 {
1544 case ALT_QSPI_CLK_POLARITY_LOW:
1545 case ALT_QSPI_CLK_POLARITY_HIGH:
1546 break;
1547 default:
1548 return ALT_E_BAD_ARG;
1549 }
1550
1551 if (cfg->cs_da > ((1 << ALT_QSPI_DELAY_NSS_WIDTH) - 1))
1552 {
1553 return ALT_E_BAD_ARG;
1554 }
1555 if (cfg->cs_dads > ((1 << ALT_QSPI_DELAY_BTWN_WIDTH) - 1))
1556 {
1557 return ALT_E_BAD_ARG;
1558 }
1559 if (cfg->cs_eot > ((1 << ALT_QSPI_DELAY_AFTER_WIDTH) - 1))
1560 {
1561 return ALT_E_BAD_ARG;
1562 }
1563 if (cfg->cs_sot > ((1 << ALT_QSPI_DELAY_INIT_WIDTH) - 1))
1564 {
1565 return ALT_E_BAD_ARG;
1566 }
1567
1568 if (cfg->rd_datacap > ((1 << ALT_QSPI_RDDATACAP_DELAY_WIDTH) - 1))
1569 {
1570 return ALT_E_BAD_ARG;
1571 }
1572
1573
1574
1575
1576 uint32_t cfgreg = alt_read_word(ALT_QSPI_CFG_ADDR);
1577 cfgreg &= ALT_QSPI_CFG_SELCLKPHASE_CLR_MSK &
1578 ALT_QSPI_CFG_SELCLKPOL_CLR_MSK;
1579 cfgreg |= ALT_QSPI_CFG_SELCLKPHASE_SET(cfg->clk_phase) |
1580 ALT_QSPI_CFG_SELCLKPOL_SET(cfg->clk_pol);
1581 alt_write_word(ALT_QSPI_CFG_ADDR, cfgreg);
1582
1583
1584 uint32_t delayreg = ALT_QSPI_DELAY_INIT_SET(cfg->cs_sot) |
1585 ALT_QSPI_DELAY_AFTER_SET(cfg->cs_eot) |
1586 ALT_QSPI_DELAY_BTWN_SET(cfg->cs_dads) |
1587 ALT_QSPI_DELAY_NSS_SET(cfg->cs_da);
1588 alt_write_word(ALT_QSPI_DELAY_ADDR, delayreg);
1589
1590
1591
1592 alt_write_word(ALT_QSPI_RDDATACAP_ADDR,
1593 ALT_QSPI_RDDATACAP_BYP_SET(1) |
1594 ALT_QSPI_RDDATACAP_DELAY_SET(cfg->rd_datacap));
1595
1596 return ALT_E_SUCCESS;
1597 }
1598
1599
1600
1601 ALT_STATUS_CODE alt_qspi_direct_disable(void)
1602 {
1603
1604
1605 alt_clrbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_ENDIRACC_SET_MSK);
1606
1607 return ALT_E_SUCCESS;
1608 }
1609
1610 ALT_STATUS_CODE alt_qspi_direct_enable(void)
1611 {
1612
1613
1614 alt_setbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_ENDIRACC_SET_MSK);
1615
1616 return ALT_E_SUCCESS;
1617 }
1618
1619 uint32_t alt_qspi_ahb_remap_address_get(void)
1620 {
1621
1622 return ALT_QSPI_REMAPADDR_VALUE_GET(alt_read_word(ALT_QSPI_REMAPADDR_ADDR));
1623 }
1624
1625 ALT_STATUS_CODE alt_qspi_ahb_remap_address_set(const uint32_t ahb_remap_addr)
1626 {
1627 if (alt_qspi_is_idle() == false)
1628 {
1629 return ALT_E_ERROR;
1630 }
1631
1632
1633 alt_setbits_word(ALT_QSPI_REMAPADDR_ADDR, ALT_QSPI_REMAPADDR_VALUE_SET(ahb_remap_addr));
1634
1635 return ALT_E_SUCCESS;
1636 }
1637
1638 ALT_STATUS_CODE alt_qspi_ahb_address_remap_disable(void)
1639 {
1640
1641
1642 alt_clrbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_ENAHBREMAP_SET_MSK);
1643
1644 return ALT_E_SUCCESS;
1645 }
1646
1647 ALT_STATUS_CODE alt_qspi_ahb_address_remap_enable(void)
1648 {
1649
1650
1651 alt_setbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_ENAHBREMAP_SET_MSK);
1652
1653 return ALT_E_SUCCESS;
1654 }
1655
1656
1657
1658 static ALT_STATUS_CODE alt_qspi_indirect_read_start_bank(uint32_t flash_addr,
1659 size_t num_bytes)
1660 {
1661 alt_write_word(ALT_QSPI_INDRDSTADDR_ADDR, flash_addr);
1662 alt_write_word(ALT_QSPI_INDRDCNT_ADDR, num_bytes);
1663 alt_write_word(ALT_QSPI_INDRD_ADDR, ALT_QSPI_INDRD_START_SET_MSK |
1664 ALT_QSPI_INDRD_IND_OPS_DONE_STAT_SET_MSK);
1665
1666 return ALT_E_SUCCESS;
1667 }
1668
1669 ALT_STATUS_CODE alt_qspi_indirect_read_start(const uint32_t flash_addr,
1670 const size_t num_bytes)
1671 {
1672
1673
1674
1675 if (flash_addr & 0x3)
1676 {
1677 return ALT_E_ERROR;
1678 }
1679
1680 if (num_bytes & 0x3)
1681 {
1682 return ALT_E_ERROR;
1683 }
1684
1685 if (num_bytes == 0)
1686 {
1687
1688
1689
1690 return ALT_E_ERROR;
1691 }
1692
1693 if (flash_addr > qspi_device_size)
1694 {
1695 return ALT_E_ERROR;
1696 }
1697
1698 if (flash_addr + num_bytes > qspi_device_size)
1699 {
1700 return ALT_E_ERROR;
1701 }
1702
1703
1704
1705 if ((flash_addr & ALT_QSPI_BANK_ADDR_MSK) != ((flash_addr + num_bytes - 1) & ALT_QSPI_BANK_ADDR_MSK))
1706 {
1707 return ALT_E_ERROR;
1708 }
1709
1710
1711 if (ALT_QSPI_INDRD_RD_STAT_GET(alt_read_word(ALT_QSPI_INDRD_ADDR)))
1712 {
1713 return ALT_E_ERROR;
1714 }
1715
1716
1717
1718 ALT_STATUS_CODE status;
1719 status = alt_qspi_device_bank_select(flash_addr >> 24);
1720 if (status != ALT_E_SUCCESS)
1721 {
1722 return status;
1723 }
1724
1725
1726
1727 return alt_qspi_indirect_read_start_bank(flash_addr,
1728 num_bytes);
1729
1730 }
1731
1732 ALT_STATUS_CODE alt_qspi_indirect_read_finish(void)
1733 {
1734 return ALT_E_SUCCESS;
1735 }
1736
1737 ALT_STATUS_CODE alt_qspi_indirect_read_cancel(void)
1738 {
1739
1740
1741 alt_write_word(ALT_QSPI_INDRD_ADDR, ALT_QSPI_INDRD_CANCEL_SET_MSK);
1742
1743 return ALT_E_SUCCESS;
1744 }
1745
1746 uint32_t alt_qspi_indirect_read_fill_level(void)
1747 {
1748
1749
1750
1751 return ALT_QSPI_SRAMFILL_INDRDPART_GET(alt_read_word(ALT_QSPI_SRAMFILL_ADDR));
1752 }
1753
1754 uint32_t alt_qspi_indirect_read_watermark_get(void)
1755 {
1756
1757 return alt_read_word(ALT_QSPI_INDRDWATER_ADDR);
1758 }
1759
1760 ALT_STATUS_CODE alt_qspi_indirect_read_watermark_set(const uint32_t watermark)
1761 {
1762
1763 if (ALT_QSPI_INDRD_RD_STAT_GET(alt_read_word(ALT_QSPI_INDRD_ADDR)))
1764 {
1765 return ALT_E_ERROR;
1766 }
1767
1768
1769 alt_write_word(ALT_QSPI_INDRDWATER_ADDR, watermark);
1770
1771 return ALT_E_SUCCESS;
1772 }
1773
1774 bool alt_qspi_indirect_read_is_complete(void)
1775 {
1776
1777
1778
1779 return (alt_read_word(ALT_QSPI_INDRD_ADDR) & ALT_QSPI_INDRD_IND_OPS_DONE_STAT_SET_MSK) != 0;
1780 }
1781
1782 static ALT_STATUS_CODE alt_qspi_indirect_write_start_bank(uint32_t flash_addr,
1783 size_t num_bytes)
1784 {
1785 alt_write_word(ALT_QSPI_INDWRSTADDR_ADDR, flash_addr);
1786 alt_write_word(ALT_QSPI_INDWRCNT_ADDR, num_bytes);
1787 alt_write_word(ALT_QSPI_INDWR_ADDR, ALT_QSPI_INDWR_START_SET_MSK |
1788 ALT_QSPI_INDWR_INDDONE_SET_MSK);
1789
1790 return ALT_E_SUCCESS;
1791 }
1792
1793 ALT_STATUS_CODE alt_qspi_indirect_write_start(const uint32_t flash_addr,
1794 const size_t num_bytes)
1795 {
1796
1797
1798
1799 if (flash_addr & 0x3)
1800 {
1801 return ALT_E_ERROR;
1802 }
1803
1804 if (num_bytes & 0x3)
1805 {
1806 return ALT_E_ERROR;
1807 }
1808
1809 if (num_bytes == 0)
1810 {
1811
1812
1813
1814 return ALT_E_ERROR;
1815 }
1816
1817 if (num_bytes > 256)
1818 {
1819
1820 return ALT_E_ERROR;
1821 }
1822
1823 if (flash_addr > qspi_device_size)
1824 {
1825 return ALT_E_ERROR;
1826 }
1827
1828 if (flash_addr + num_bytes > qspi_device_size)
1829 {
1830 return ALT_E_ERROR;
1831 }
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843 if ((flash_addr & ALT_QSPI_PAGE_ADDR_MSK) != ((flash_addr + num_bytes - 1) & ALT_QSPI_PAGE_ADDR_MSK))
1844 {
1845 return ALT_E_ERROR;
1846 }
1847
1848
1849 if (ALT_QSPI_INDWR_RDSTAT_GET(alt_read_word(ALT_QSPI_INDWR_ADDR)))
1850 {
1851 return ALT_E_ERROR;
1852 }
1853
1854
1855
1856 ALT_STATUS_CODE status = ALT_E_SUCCESS;
1857 status = alt_qspi_device_bank_select(flash_addr >> 24);
1858 if (status != ALT_E_SUCCESS)
1859 {
1860 return status;
1861 }
1862
1863
1864
1865 return alt_qspi_indirect_write_start_bank(flash_addr,
1866 num_bytes);
1867 }
1868
1869 ALT_STATUS_CODE alt_qspi_indirect_write_finish(void)
1870 {
1871 #if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT
1872 return alt_qspi_N25Q_flag_wait_for_program(ALT_QSPI_TIMEOUT_INFINITE);
1873 #else
1874 return ALT_E_SUCCESS;
1875 #endif
1876 }
1877
1878 ALT_STATUS_CODE alt_qspi_indirect_write_cancel(void)
1879 {
1880 ALT_STATUS_CODE status = ALT_E_SUCCESS;
1881
1882 #if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT
1883 if (status == ALT_E_SUCCESS)
1884 {
1885 status = alt_qspi_N25Q_flag_wait_for_program(ALT_QSPI_TIMEOUT_INFINITE);
1886 }
1887 #endif
1888
1889 if (status == ALT_E_SUCCESS)
1890 {
1891
1892
1893 alt_write_word(ALT_QSPI_INDWR_ADDR, ALT_QSPI_INDWR_CANCEL_SET_MSK);
1894 }
1895
1896 return status;
1897 }
1898
1899 uint32_t alt_qspi_indirect_write_fill_level(void)
1900 {
1901
1902
1903
1904 return ALT_QSPI_SRAMFILL_INDWRPART_GET(alt_read_word(ALT_QSPI_SRAMFILL_ADDR));
1905 }
1906
1907 uint32_t alt_qspi_indirect_write_watermark_get(void)
1908 {
1909
1910 return alt_read_word(ALT_QSPI_INDWRWATER_ADDR);
1911 }
1912
1913 ALT_STATUS_CODE alt_qspi_indirect_write_watermark_set(const uint32_t watermark)
1914 {
1915
1916 if (ALT_QSPI_INDWR_RDSTAT_GET(alt_read_word(ALT_QSPI_INDWR_ADDR)))
1917 {
1918 return ALT_E_ERROR;
1919 }
1920
1921
1922 alt_write_word(ALT_QSPI_INDWRWATER_ADDR, watermark);
1923
1924 return ALT_E_SUCCESS;
1925 }
1926
1927 bool alt_qspi_indirect_write_is_complete(void)
1928 {
1929
1930
1931
1932 return (alt_read_word(ALT_QSPI_INDWR_ADDR) & ALT_QSPI_INDWR_INDDONE_SET_MSK) != 0;
1933 }
1934
1935
1936
1937 uint32_t alt_qspi_sram_partition_get(void)
1938 {
1939
1940
1941
1942
1943
1944 return ALT_QSPI_SRAMPART_ADDR_GET(alt_read_word(ALT_QSPI_SRAMPART_ADDR));
1945 }
1946
1947 ALT_STATUS_CODE alt_qspi_sram_partition_set(const uint32_t read_part_size)
1948 {
1949 if (read_part_size > ((1 << ALT_QSPI_SRAMPART_ADDR_WIDTH) - 1))
1950 {
1951 return ALT_E_ARG_RANGE;
1952 }
1953
1954 alt_replbits_word(ALT_QSPI_SRAMPART_ADDR,
1955 ALT_QSPI_SRAMPART_ADDR_SET_MSK,
1956 ALT_QSPI_SRAMPART_ADDR_SET(read_part_size));
1957
1958 return ALT_E_SUCCESS;
1959 }
1960
1961
1962
1963
1964 static ALT_STATUS_CODE alt_qspi_erase_subsector_bank(uint32_t addr)
1965 {
1966 ALT_STATUS_CODE status = ALT_E_SUCCESS;
1967
1968 if (status == ALT_E_SUCCESS)
1969 {
1970 status = alt_qspi_device_wren();
1971 }
1972
1973 if (status == ALT_E_SUCCESS)
1974 {
1975 status = alt_qspi_stig_addr_cmd(ALT_QSPI_STIG_OPCODE_SUBSEC_ERASE, 0, addr, 10000);
1976 }
1977
1978 #if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT
1979 if (status == ALT_E_SUCCESS)
1980 {
1981 status = alt_qspi_N25Q_flag_wait_for_erase(ALT_QSPI_TIMEOUT_INFINITE);
1982 }
1983 #endif
1984
1985 return status;
1986 }
1987
1988 ALT_STATUS_CODE alt_qspi_erase_subsector(const uint32_t addr)
1989 {
1990 ALT_STATUS_CODE status = ALT_E_SUCCESS;
1991
1992 if (status == ALT_E_SUCCESS)
1993 {
1994 status = alt_qspi_device_bank_select(addr >> 24);
1995 }
1996
1997 if (status == ALT_E_SUCCESS)
1998 {
1999 status = alt_qspi_erase_subsector_bank(addr);
2000 }
2001
2002 return status;
2003 }
2004
2005 ALT_STATUS_CODE alt_qspi_erase_sector(const uint32_t addr)
2006 {
2007 ALT_STATUS_CODE status = ALT_E_SUCCESS;
2008
2009 if (status == ALT_E_SUCCESS)
2010 {
2011 status = alt_qspi_device_bank_select(addr >> 24);
2012 }
2013
2014 if (status == ALT_E_SUCCESS)
2015 {
2016 status = alt_qspi_device_wren();
2017 }
2018
2019 if (status == ALT_E_SUCCESS)
2020 {
2021 status = alt_qspi_stig_addr_cmd(ALT_QSPI_STIG_OPCODE_SEC_ERASE, 0, addr, ALT_QSPI_TIMEOUT_INFINITE);
2022 }
2023
2024 #if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT
2025 if (status == ALT_E_SUCCESS)
2026 {
2027 status = alt_qspi_N25Q_flag_wait_for_erase(ALT_QSPI_TIMEOUT_INFINITE);
2028 }
2029 #endif
2030
2031 return status;
2032 }
2033
2034 ALT_STATUS_CODE alt_qspi_erase_chip(void)
2035 {
2036 ALT_STATUS_CODE status = ALT_E_SUCCESS;
2037
2038 if (qspi_device_size >= (2 * ALT_QSPI_N25Q_DIE_SIZE))
2039 {
2040
2041
2042
2043 dprintf("DEBUG[QSPI]: erase[chip]: FYI, wait time is ~800s for 128 MiB.\n");
2044
2045 uint32_t die_count = qspi_device_size / ALT_QSPI_N25Q_DIE_SIZE;
2046
2047 for (int i = 0; i < die_count; ++i)
2048 {
2049 if (status != ALT_E_SUCCESS)
2050 {
2051 break;
2052 }
2053
2054 dprintf("DEBUG[QSPI]: Erase chip: die = %d, total = %" PRIu32 ".\n", i, die_count);
2055
2056 if (status == ALT_E_SUCCESS)
2057 {
2058 status = alt_qspi_device_bank_select(i * (ALT_QSPI_N25Q_DIE_SIZE / ALT_QSPI_BANK_SIZE));
2059 }
2060
2061 if (status == ALT_E_SUCCESS)
2062 {
2063 status = alt_qspi_device_wren();
2064 }
2065
2066 if (status == ALT_E_SUCCESS)
2067 {
2068 status = alt_qspi_stig_addr_cmd(ALT_QSPI_STIG_OPCODE_DIE_ERASE, 0,
2069 i * ALT_QSPI_N25Q_DIE_SIZE,
2070 ALT_QSPI_TIMEOUT_INFINITE);
2071 }
2072
2073 #if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT
2074 if (status == ALT_E_SUCCESS)
2075 {
2076 status = alt_qspi_N25Q_flag_wait_for_erase(ALT_QSPI_TIMEOUT_INFINITE);
2077 }
2078 #endif
2079 }
2080 }
2081 else
2082 {
2083
2084
2085 dprintf("DEBUG[QSPI]: Bulk erase.\n");
2086
2087 if (status == ALT_E_SUCCESS)
2088 {
2089 status = alt_qspi_device_bank_select(0);
2090 }
2091
2092 if (status == ALT_E_SUCCESS)
2093 {
2094 status = alt_qspi_device_wren();
2095 }
2096
2097 if (status == ALT_E_SUCCESS)
2098 {
2099
2100 status = alt_qspi_stig_addr_cmd(ALT_QSPI_STIG_OPCODE_BULK_ERASE, 0,
2101 0,
2102 ALT_QSPI_TIMEOUT_INFINITE);
2103 }
2104
2105 #if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT
2106 if (status == ALT_E_SUCCESS)
2107 {
2108 status = alt_qspi_N25Q_flag_wait_for_erase(ALT_QSPI_TIMEOUT_INFINITE);
2109 }
2110 #endif
2111 }
2112
2113 return status;
2114 }
2115
2116
2117
2118 ALT_STATUS_CODE alt_qspi_dma_disable(void)
2119 {
2120
2121
2122 alt_clrbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_ENDMA_SET_MSK);
2123
2124 return ALT_E_SUCCESS;
2125 }
2126
2127 ALT_STATUS_CODE alt_qspi_dma_enable(void)
2128 {
2129
2130
2131 alt_setbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_ENDMA_SET_MSK);
2132
2133 return ALT_E_SUCCESS;
2134 }
2135
2136 ALT_STATUS_CODE alt_qspi_dma_config_get(uint32_t * single_type_sz,
2137 uint32_t * burst_type_sz)
2138 {
2139
2140 uint32_t dmaper = alt_read_word(ALT_QSPI_DMAPER_ADDR);
2141
2142
2143
2144 *single_type_sz = 1 << ALT_QSPI_DMAPER_NUMSGLREQBYTES_GET(dmaper);
2145 *burst_type_sz = 1 << ALT_QSPI_DMAPER_NUMBURSTREQBYTES_GET(dmaper);
2146
2147 return ALT_E_SUCCESS;
2148 }
2149
2150
2151
2152
2153 static bool is_pow_2(uint32_t n)
2154 {
2155 return ((n > 0) && ((n & (n - 1)) == 0));
2156 }
2157
2158
2159
2160
2161 static uint32_t log2u(uint32_t value)
2162 {
2163 uint32_t exp = 0;
2164 while ((exp < 32) && (value != (1 << exp)))
2165 {
2166 ++exp;
2167 }
2168 return exp;
2169 }
2170
2171 ALT_STATUS_CODE alt_qspi_dma_config_set(const uint32_t single_type_sz,
2172 const uint32_t burst_type_sz)
2173 {
2174 if (alt_qspi_is_idle() == false)
2175 {
2176 return ALT_E_ERROR;
2177 }
2178
2179 if (single_type_sz < 4)
2180 {
2181 return ALT_E_ERROR;
2182 }
2183
2184 if (burst_type_sz < 4)
2185 {
2186 return ALT_E_ERROR;
2187 }
2188
2189 if (burst_type_sz < single_type_sz)
2190 {
2191 return ALT_E_ERROR;
2192 }
2193
2194 const uint32_t single_type_sz_max = 1 << ((1 << ALT_QSPI_DMAPER_NUMSGLREQBYTES_WIDTH) - 1);
2195 const uint32_t burst_type_sz_max = 1 << ((1 << ALT_QSPI_DMAPER_NUMBURSTREQBYTES_WIDTH) - 1);
2196
2197
2198 if ( (single_type_sz > single_type_sz_max) || !is_pow_2(single_type_sz)
2199 || (burst_type_sz > burst_type_sz_max) || !is_pow_2(burst_type_sz)
2200 )
2201 {
2202 return ALT_E_ARG_RANGE;
2203 }
2204
2205
2206 uint32_t dmaper = alt_read_word(ALT_QSPI_DMAPER_ADDR);
2207 dmaper &= ALT_QSPI_DMAPER_NUMBURSTREQBYTES_CLR_MSK &
2208 ALT_QSPI_DMAPER_NUMSGLREQBYTES_CLR_MSK;
2209 dmaper |= ALT_QSPI_DMAPER_NUMBURSTREQBYTES_SET(log2u(burst_type_sz)) |
2210 ALT_QSPI_DMAPER_NUMSGLREQBYTES_SET(log2u(single_type_sz));
2211 alt_write_word(ALT_QSPI_DMAPER_ADDR, dmaper);
2212
2213 return ALT_E_SUCCESS;
2214 }
2215
2216
2217
2218
2219
2220
2221
2222 static ALT_STATUS_CODE alt_qspi_stig_cmd_helper(uint32_t reg_value, uint32_t timeout)
2223 {
2224 ALT_STATUS_CODE status = ALT_E_SUCCESS;
2225 bool infinite = (timeout == ALT_QSPI_TIMEOUT_INFINITE);
2226
2227 alt_write_word(ALT_QSPI_FLSHCMD_ADDR, reg_value);
2228 alt_write_word(ALT_QSPI_FLSHCMD_ADDR, reg_value | ALT_QSPI_FLSHCMD_EXECCMD_E_EXECUTE);
2229
2230 do
2231 {
2232 reg_value = alt_read_word(ALT_QSPI_FLSHCMD_ADDR);
2233 if (!(reg_value & ALT_QSPI_FLSHCMD_CMDEXECSTAT_SET_MSK))
2234 {
2235 break;
2236 }
2237
2238 } while (timeout-- || infinite);
2239
2240 if (timeout == (uint32_t)-1 && !infinite)
2241 {
2242 status = ALT_E_TMO;
2243 }
2244
2245 return status;
2246 }
2247
2248 ALT_STATUS_CODE alt_qspi_stig_cmd(uint32_t opcode, uint32_t dummy, uint32_t timeout)
2249 {
2250 if (dummy > ((1 << ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_WIDTH) - 1))
2251 {
2252 return ALT_E_ERROR;
2253 }
2254
2255 uint32_t reg = ALT_QSPI_FLSHCMD_CMDOPCODE_SET(opcode) |
2256 ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_SET(dummy);
2257
2258 return alt_qspi_stig_cmd_helper(reg, timeout);
2259 }
2260
2261 ALT_STATUS_CODE alt_qspi_stig_rd_cmd(uint8_t opcode,
2262 uint32_t dummy,
2263 uint32_t num_bytes,
2264 uint32_t * output,
2265 uint32_t timeout)
2266 {
2267 if (dummy > ((1 << ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_WIDTH) - 1))
2268 {
2269 return ALT_E_ERROR;
2270 }
2271
2272
2273 if ((num_bytes > 8) || (num_bytes == 0))
2274 {
2275 return ALT_E_BAD_ARG;
2276 }
2277
2278 uint32_t reg_value =
2279 ALT_QSPI_FLSHCMD_CMDOPCODE_SET(opcode) |
2280 ALT_QSPI_FLSHCMD_ENRDDATA_SET(ALT_QSPI_FLSHCMD_ENRDDATA_E_EN) |
2281 ALT_QSPI_FLSHCMD_NUMRDDATABYTES_SET(num_bytes - 1) |
2282 ALT_QSPI_FLSHCMD_ENCMDADDR_SET(ALT_QSPI_FLSHCMD_ENCMDADDR_E_DISD) |
2283 ALT_QSPI_FLSHCMD_ENMODBIT_SET(ALT_QSPI_FLSHCMD_ENMODBIT_E_DISD) |
2284 ALT_QSPI_FLSHCMD_NUMADDRBYTES_SET(0) |
2285 ALT_QSPI_FLSHCMD_ENWRDATA_SET(ALT_QSPI_FLSHCMD_ENWRDATA_E_NOACTION) |
2286 ALT_QSPI_FLSHCMD_NUMWRDATABYTES_SET(0) |
2287 ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_SET(dummy);
2288
2289 ALT_STATUS_CODE status = ALT_E_SUCCESS;
2290
2291 status = alt_qspi_stig_cmd_helper(reg_value, timeout);
2292 if (status != ALT_E_SUCCESS)
2293 {
2294 return status;
2295 }
2296
2297 output[0] = alt_read_word(ALT_QSPI_FLSHCMDRDDATALO_ADDR);
2298
2299 if (num_bytes > 4)
2300 {
2301 output[1] = alt_read_word(ALT_QSPI_FLSHCMDRDDATAUP_ADDR);
2302 }
2303
2304 return ALT_E_SUCCESS;
2305 }
2306
2307 ALT_STATUS_CODE alt_qspi_stig_wr_cmd(uint8_t opcode,
2308 uint32_t dummy,
2309 uint32_t num_bytes,
2310 const uint32_t * input,
2311 uint32_t timeout)
2312 {
2313 if (dummy > ((1 << ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_WIDTH) - 1))
2314 {
2315 return ALT_E_ERROR;
2316 }
2317
2318
2319 if ((num_bytes > 8) || (num_bytes == 0))
2320 {
2321 return ALT_E_BAD_ARG;
2322 }
2323
2324 uint32_t reg_value =
2325 ALT_QSPI_FLSHCMD_CMDOPCODE_SET(opcode) |
2326 ALT_QSPI_FLSHCMD_ENRDDATA_SET(ALT_QSPI_FLSHCMD_ENRDDATA_E_NOACTION) |
2327 ALT_QSPI_FLSHCMD_NUMRDDATABYTES_SET(0) |
2328 ALT_QSPI_FLSHCMD_ENCMDADDR_SET(ALT_QSPI_FLSHCMD_ENCMDADDR_E_DISD) |
2329 ALT_QSPI_FLSHCMD_ENMODBIT_SET(ALT_QSPI_FLSHCMD_ENMODBIT_E_DISD) |
2330 ALT_QSPI_FLSHCMD_NUMADDRBYTES_SET(0) |
2331 ALT_QSPI_FLSHCMD_ENWRDATA_SET(ALT_QSPI_FLSHCMD_ENWRDATA_E_WRDATABYTES) |
2332 ALT_QSPI_FLSHCMD_NUMWRDATABYTES_SET(num_bytes - 1) |
2333 ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_SET(dummy);
2334
2335 alt_write_word(ALT_QSPI_FLSHCMDWRDATALO_ADDR, input[0]);
2336
2337 if (num_bytes > 4)
2338 {
2339 alt_write_word(ALT_QSPI_FLSHCMDWRDATAUP_ADDR, input[1]);
2340 }
2341
2342 return alt_qspi_stig_cmd_helper(reg_value, timeout);
2343 }
2344
2345 ALT_STATUS_CODE alt_qspi_stig_addr_cmd(uint8_t opcode,
2346 uint32_t dummy,
2347 uint32_t address,
2348 uint32_t timeout)
2349 {
2350 if (dummy > ((1 << ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_WIDTH) - 1))
2351 {
2352 return ALT_E_ERROR;
2353 }
2354
2355 uint32_t reg = ALT_QSPI_FLSHCMD_CMDOPCODE_SET(opcode) |
2356 ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_SET(dummy);
2357
2358 reg |= ALT_QSPI_FLSHCMD_ENCMDADDR_SET(ALT_QSPI_FLSHCMD_ENCMDADDR_E_END);
2359 reg |= ALT_QSPI_FLSHCMD_NUMADDRBYTES_SET(ALT_QSPI_FLSHCMD_NUMADDRBYTES_E_ADDRBYTE3);
2360
2361 alt_write_word(ALT_QSPI_FLSHCMDADDR_ADDR, address);
2362
2363 return alt_qspi_stig_cmd_helper(reg, timeout);
2364 }
2365
2366
2367
2368 ALT_STATUS_CODE alt_qspi_device_wren(void)
2369 {
2370
2371 return alt_qspi_stig_cmd(ALT_QSPI_STIG_OPCODE_WREN, 0, 10000);
2372 }
2373
2374 ALT_STATUS_CODE alt_qspi_device_wrdis(void)
2375 {
2376
2377 return alt_qspi_stig_cmd(ALT_QSPI_STIG_OPCODE_WRDIS, 0, 10000);
2378 }
2379
2380 ALT_STATUS_CODE alt_qspi_device_rdid(uint32_t * rdid)
2381 {
2382
2383 return alt_qspi_stig_rd_cmd(ALT_QSPI_STIG_OPCODE_RDID, 0, 4, rdid, 10000);
2384 }
2385
2386 ALT_STATUS_CODE alt_qspi_discovery_parameter(uint32_t * param)
2387 {
2388
2389
2390 return alt_qspi_stig_rd_cmd(ALT_QSPI_STIG_OPCODE_DISCVR_PARAM, 8, 8, param, 10000);
2391 }
2392
2393 ALT_STATUS_CODE alt_qspi_device_bank_select(uint32_t bank)
2394 {
2395 ALT_STATUS_CODE status = ALT_E_SUCCESS;
2396 dprintf("DEBUG[QSPI]: bank_select(): switching to bank 0x%" PRIu32 ".\n", bank);
2397
2398 if (status == ALT_E_SUCCESS)
2399 {
2400 status = alt_qspi_device_wren();
2401 }
2402
2403 if (status == ALT_E_SUCCESS)
2404 {
2405 status = alt_qspi_stig_wr_cmd(ALT_QSPI_STIG_OPCODE_WR_EXT_REG, 0, 1, &bank, 10000);
2406 }
2407
2408 if (status == ALT_E_SUCCESS)
2409 {
2410 status = alt_qspi_device_wrdis();
2411 }
2412
2413 return status;
2414 }
2415
2416
2417
2418 static bool alt_qspi_is_enabled(void)
2419 {
2420 uint32_t cfg = alt_read_word(ALT_QSPI_CFG_ADDR);
2421
2422 if (cfg & ALT_QSPI_CFG_EN_SET_MSK)
2423 {
2424 return true;
2425 }
2426 else
2427 {
2428 return false;
2429 }
2430 }
2431
2432 ALT_STATUS_CODE alt_qspi_ecc_start(void * block, size_t size)
2433 {
2434 if (size < (ALT_QSPI_PAGE_SIZE * 8))
2435 {
2436 return ALT_E_ERROR;
2437 }
2438
2439 if (alt_qspi_is_enabled() == false)
2440 {
2441 return ALT_E_ERROR;
2442 }
2443
2444 if (alt_qspi_is_idle() == false)
2445 {
2446 return ALT_E_ERROR;
2447 }
2448
2449 ALT_STATUS_CODE status = ALT_E_SUCCESS;
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461 uint32_t sram_orig = alt_qspi_sram_partition_get();
2462 dprintf("DEBUG[QSPI][ECC]: Save original SRAM as %" PRIu32 ".\n", sram_orig);
2463
2464
2465
2466 uint32_t sram_fill = (1 << ALT_QSPI_SRAMPART_ADDR_WIDTH) - 2;
2467 alt_qspi_sram_partition_set(sram_fill);
2468 dprintf("DEBUG[QSPI][ECC]: Set new SRAM as %" PRIu32 ".\n", sram_fill);
2469
2470
2471
2472 dprintf("DEBUG[QSPI][ECC]: Enable ECC in SysMgr.\n");
2473 alt_write_word(ALT_SYSMGR_ECC_QSPI_ADDR, ALT_SYSMGR_ECC_QSPI_EN_SET_MSK);
2474
2475
2476
2477
2478
2479
2480
2481 if (status == ALT_E_SUCCESS)
2482 {
2483 dprintf("DEBUG[QSPI][ECC]: Start indirect read PAGE * 8.\n");
2484 status = alt_qspi_indirect_read_start(0x0, ALT_QSPI_PAGE_SIZE * 8);
2485 }
2486
2487
2488
2489 if (status == ALT_E_SUCCESS)
2490 {
2491 dprintf("DEBUG[QSPI][ECC]: Reading out 1 page ...\n");
2492
2493 uint32_t read_size = 0;
2494 char * buffer = block;
2495 while (read_size < ALT_QSPI_PAGE_SIZE)
2496 {
2497 uint32_t level = alt_qspi_indirect_read_fill_level();
2498 level = MIN(level, (ALT_QSPI_PAGE_SIZE - read_size) / sizeof(uint32_t));
2499
2500 uint32_t * data = (uint32_t *)(&buffer[read_size]);
2501 for (uint32_t i = 0; i < level; ++i)
2502 {
2503 *data = alt_read_word(ALT_QSPIDATA_ADDR);
2504 ++data;
2505 }
2506
2507 read_size += level * sizeof(uint32_t);
2508 }
2509
2510 if (read_size != ALT_QSPI_PAGE_SIZE)
2511 {
2512 status = ALT_E_ERROR;
2513 }
2514 }
2515
2516
2517
2518 if (status == ALT_E_SUCCESS)
2519 {
2520 dprintf("DEBUG[QSPI][ECC]: Waiting for read fill level ...\n");
2521
2522 uint32_t timeout = 10000;
2523
2524 while (alt_qspi_indirect_read_fill_level() < sram_fill)
2525 {
2526 if (--timeout == 0)
2527 {
2528 dprintf("DEBUG[QSPI][ECC]: Waiting for read fill timeout !!!\n");
2529 status = ALT_E_TMO;
2530 break;
2531 }
2532 }
2533 }
2534
2535
2536
2537
2538
2539 if (status == ALT_E_SUCCESS)
2540 {
2541 dprintf("DEBUG[QSPI][ECC]: Start indirect write PAGE.\n");
2542 status = alt_qspi_indirect_write_start(0x0, ALT_QSPI_PAGE_SIZE);
2543 }
2544
2545 if (status == ALT_E_SUCCESS)
2546 {
2547 dprintf("DEBUG[QSPI][ECC]: Writing in 1 page ...\n");
2548
2549 uint32_t write_size = 0;
2550 char * buffer = block;
2551
2552 while (write_size < ALT_QSPI_PAGE_SIZE)
2553 {
2554 uint32_t space = 2 - alt_qspi_indirect_write_fill_level();
2555 if (space == 0)
2556 {
2557 dprintf("DEBUG[QSPI][ECC]: Write FIFO filled at write_size = %" PRIu32 ".\n", write_size);
2558
2559
2560 break;
2561 }
2562
2563 space = MIN(space, (ALT_QSPI_PAGE_SIZE - write_size) / sizeof(uint32_t));
2564
2565 uint32_t * data = (uint32_t *)(&buffer[write_size]);
2566 for (uint32_t i = 0; i < space; ++i)
2567 {
2568 alt_write_word(ALT_QSPIDATA_ADDR, *data);
2569 ++data;
2570 }
2571
2572 write_size += space * sizeof(uint32_t);
2573 }
2574
2575 if (write_size != ALT_QSPI_PAGE_SIZE)
2576 {
2577 dprintf("DEBUG[QSPI][ECC]: Cancel indirect write.\n");
2578 status = alt_qspi_indirect_write_cancel();
2579 }
2580 }
2581
2582 if (status == ALT_E_SUCCESS)
2583 {
2584 dprintf("DEBUG[QSPI][ECC]: Finish indirect write.\n");
2585 status = alt_qspi_indirect_write_finish();
2586 }
2587
2588
2589
2590 if (status == ALT_E_SUCCESS)
2591 {
2592 dprintf("DEBUG[QSPI][ECC]: Cancel indirect read.\n");
2593 status = alt_qspi_indirect_read_cancel();
2594 }
2595
2596 if (status == ALT_E_SUCCESS)
2597 {
2598 dprintf("DEBUG[QSPI][ECC]: Finish indirect read.\n");
2599 status = alt_qspi_indirect_read_finish();
2600 }
2601
2602
2603
2604 if (status == ALT_E_SUCCESS)
2605 {
2606 dprintf("DEBUG[QSPI][ECC]: Clear any pending spurious QSPI ECC interrupts.\n");
2607
2608 alt_write_word(ALT_SYSMGR_ECC_QSPI_ADDR,
2609 ALT_SYSMGR_ECC_QSPI_EN_SET_MSK
2610 | ALT_SYSMGR_ECC_QSPI_SERR_SET_MSK
2611 | ALT_SYSMGR_ECC_QSPI_DERR_SET_MSK);
2612 }
2613
2614
2615
2616
2617
2618 if (status == ALT_E_SUCCESS)
2619 {
2620 dprintf("DEBUG[QSPI][ECC]: Restore original SRAM as %" PRIu32 ".\n", sram_orig);
2621 status = alt_qspi_sram_partition_set(sram_orig);
2622 }
2623
2624 return status;
2625 }