diff --git a/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c b/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c index 7d7d55f..a0fc034 100644 --- a/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c +++ b/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c @@ -15,7 +15,7 @@ #include #include -#include "drivers/qspi/cadence_qspi.h" +#include "qspi/cadence_qspi.h" /* As we need to be able to keep state for seek, only one file can be open * at a time. Make this a structure and point to the entity->info. When we diff --git a/plat/intel/soc/common/drivers/qspi/cadence_qspi.c b/plat/intel/soc/common/drivers/qspi/cadence_qspi.c new file mode 100644 index 0000000..506a633 --- /dev/null +++ b/plat/intel/soc/common/drivers/qspi/cadence_qspi.c @@ -0,0 +1,824 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include "cadence_qspi.h" +#include + +#define LESS(a, b) (((a) < (b)) ? (a) : (b)) +#define MORE(a, b) (((a) > (b)) ? (a) : (b)) + + +uint32_t qspi_device_size; +int cad_qspi_cs; + +int cad_qspi_idle(void) +{ + return (mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG) + & CAD_QSPI_CFG_IDLE) >> 31; +} + +int cad_qspi_set_baudrate_div(uint32_t div) +{ + if (div > 0xf) + return CAD_INVALID; + + mmio_clrsetbits_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, + ~CAD_QSPI_CFG_BAUDDIV_MSK, + CAD_QSPI_CFG_BAUDDIV(div)); + + return 0; +} + +int cad_qspi_configure_dev_size(uint32_t addr_bytes, + uint32_t bytes_per_dev, uint32_t bytes_per_block) +{ + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DEVSZ, + CAD_QSPI_DEVSZ_ADDR_BYTES(addr_bytes) | + CAD_QSPI_DEVSZ_BYTES_PER_PAGE(bytes_per_dev) | + CAD_QSPI_DEVSZ_BYTES_PER_BLOCK(bytes_per_block)); + return 0; +} + +int cad_qspi_set_read_config(uint32_t opcode, uint32_t instr_type, + uint32_t addr_type, uint32_t data_type, + uint32_t mode_bit, uint32_t dummy_clk_cycle) +{ + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DEVRD, + CAD_QSPI_DEV_OPCODE(opcode) | + CAD_QSPI_DEV_INST_TYPE(instr_type) | + CAD_QSPI_DEV_ADDR_TYPE(addr_type) | + CAD_QSPI_DEV_DATA_TYPE(data_type) | + CAD_QSPI_DEV_MODE_BIT(mode_bit) | + CAD_QSPI_DEV_DUMMY_CLK_CYCLE(dummy_clk_cycle)); + + return 0; +} + +int cat_qspi_set_write_config(uint32_t addr_type, uint32_t data_type, + uint32_t mode_bit, uint32_t dummy_clk_cycle) +{ + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DEVWR, + CAD_QSPI_DEV_ADDR_TYPE(addr_type) | + CAD_QSPI_DEV_DATA_TYPE(data_type) | + CAD_QSPI_DEV_MODE_BIT(mode_bit) | + CAD_QSPI_DEV_DUMMY_CLK_CYCLE(dummy_clk_cycle)); + + return 0; +} + +int cad_qspi_timing_config(uint32_t clkphase, uint32_t clkpol, uint32_t csda, + uint32_t csdads, uint32_t cseot, uint32_t cssot, + uint32_t rddatacap) +{ + uint32_t cfg = mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG); + + cfg &= CAD_QSPI_CFG_SELCLKPHASE_CLR_MSK & + CAD_QSPI_CFG_SELCLKPOL_CLR_MSK; + cfg |= CAD_QSPI_SELCLKPHASE(clkphase) | CAD_QSPI_SELCLKPOL(clkpol); + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, cfg); + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DELAY, + CAD_QSPI_DELAY_CSSOT(cssot) | CAD_QSPI_DELAY_CSEOT(cseot) | + CAD_QSPI_DELAY_CSDADS(csdads) | CAD_QSPI_DELAY_CSDA(csda)); + + return 0; +} + +int cad_qspi_stig_cmd_helper(int cs, uint32_t cmd) +{ + uint32_t count = 0; + + /* chip select */ + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, + (mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG) + & CAD_QSPI_CFG_CS_MSK) | CAD_QSPI_CFG_CS(cs)); + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD, cmd); + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD, + cmd | CAD_QSPI_FLASHCMD_EXECUTE); + + do { + uint32_t reg = mmio_read_32(CAD_QSPI_OFFSET + + CAD_QSPI_FLASHCMD); + if (!(reg & CAD_QSPI_FLASHCMD_EXECUTE_STAT)) + break; + count++; + } while (count < CAD_QSPI_COMMAND_TIMEOUT); + + if (count >= CAD_QSPI_COMMAND_TIMEOUT) { + ERROR("Error sending QSPI command %x, timed out\n", + cmd); + return CAD_QSPI_ERROR; + } + + return 0; +} + +int cad_qspi_stig_cmd(uint32_t opcode, uint32_t dummy) +{ + if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) { + ERROR("Faulty dummy bytes\n"); + return -1; + } + + return cad_qspi_stig_cmd_helper(cad_qspi_cs, + CAD_QSPI_FLASHCMD_OPCODE(opcode) | + CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES(dummy)); +} + +int cad_qspi_stig_read_cmd(uint32_t opcode, uint32_t dummy, uint32_t num_bytes, + uint32_t *output) +{ + if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) { + ERROR("Faulty dummy byes\n"); + return -1; + } + + if ((num_bytes > 8) || (num_bytes == 0)) + return -1; + + uint32_t cmd = + CAD_QSPI_FLASHCMD_OPCODE(opcode) | + CAD_QSPI_FLASHCMD_ENRDDATA(1) | + CAD_QSPI_FLASHCMD_NUMRDDATABYTES(num_bytes - 1) | + CAD_QSPI_FLASHCMD_ENCMDADDR(0) | + CAD_QSPI_FLASHCMD_ENMODEBIT(0) | + CAD_QSPI_FLASHCMD_NUMADDRBYTES(0) | + CAD_QSPI_FLASHCMD_ENWRDATA(0) | + CAD_QSPI_FLASHCMD_NUMWRDATABYTES(0) | + CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(dummy); + + if (cad_qspi_stig_cmd_helper(cad_qspi_cs, cmd)) { + ERROR("failed to send stig cmd"); + return -1; + } + + output[0] = mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_RDDATA0); + + if (num_bytes > 4) { + output[1] = mmio_read_32(CAD_QSPI_OFFSET + + CAD_QSPI_FLASHCMD_RDDATA1); + } + + return 0; +} + +int cad_qspi_stig_wr_cmd(uint32_t opcode, uint32_t dummy, uint32_t num_bytes, + uint32_t *input) +{ + if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) { + ERROR("Faulty dummy byes\n"); + return -1; + } + + if ((num_bytes > 8) || (num_bytes == 0)) + return -1; + + uint32_t cmd = CAD_QSPI_FLASHCMD_OPCODE(opcode) | + CAD_QSPI_FLASHCMD_ENRDDATA(0) | + CAD_QSPI_FLASHCMD_NUMRDDATABYTES(0) | + CAD_QSPI_FLASHCMD_ENCMDADDR(0) | + CAD_QSPI_FLASHCMD_ENMODEBIT(0) | + CAD_QSPI_FLASHCMD_NUMADDRBYTES(0) | + CAD_QSPI_FLASHCMD_ENWRDATA(1) | + CAD_QSPI_FLASHCMD_NUMWRDATABYTES(num_bytes - 1) | + CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(dummy); + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_WRDATA0, input[0]); + + if (num_bytes > 4) + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_WRDATA1, + input[1]); + + return cad_qspi_stig_cmd_helper(cad_qspi_cs, cmd); +} + +int cad_qspi_stig_addr_cmd(uint32_t opcode, uint32_t dummy, uint32_t addr) +{ + uint32_t cmd; + + if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) + return -1; + + cmd = CAD_QSPI_FLASHCMD_OPCODE(opcode) | + CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(dummy) | + CAD_QSPI_FLASHCMD_ENCMDADDR(1) | + CAD_QSPI_FLASHCMD_NUMADDRBYTES(2); + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_ADDR, addr); + + return cad_qspi_stig_cmd_helper(cad_qspi_cs, cmd); +} + +int cad_qspi_device_bank_select(uint32_t bank) +{ + int status = 0; + + status = cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WREN, 0); + if (status != 0) + return status; + + status = cad_qspi_stig_wr_cmd(CAD_QSPI_STIG_OPCODE_WREN_EXT_REG, + 0, 1, &bank); + if (status != 0) + return status; + + return cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WRDIS, 0); +} + +int cad_qspi_device_status(uint32_t *status) +{ + return cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDSR, 0, 1, status); +} + +#if CAD_QSPI_MICRON_N25Q_SUPPORT +int cad_qspi_n25q_enable(void) +{ + cad_qspi_set_read_config(QSPI_FAST_READ, CAD_QSPI_INST_SINGLE, + CAD_QSPI_ADDR_FASTREAD, CAT_QSPI_ADDR_SINGLE_IO, 1, + 0); + return 0; +} + +int cad_qspi_n25q_wait_for_program_and_erase(int program_only) +{ + uint32_t status, flag_sr; + int count = 0; + + while (count < CAD_QSPI_COMMAND_TIMEOUT) { + status = cad_qspi_device_status(&status); + if (status != 0) { + ERROR("Error getting device status\n"); + return -1; + } + if (!CAD_QSPI_STIG_SR_BUSY(status)) + break; + count++; + } + + if (count >= CAD_QSPI_COMMAND_TIMEOUT) { + ERROR("Timed out waiting for idle\n"); + return -1; + } + + count = 0; + + while (count < CAD_QSPI_COMMAND_TIMEOUT) { + status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDFLGSR, + 0, 1, &flag_sr); + if (status != 0) { + ERROR("Error waiting program and erase.\n"); + return status; + } + + if ((program_only && + CAD_QSPI_STIG_FLAGSR_PROGRAMREADY(flag_sr)) || + (!program_only && + CAD_QSPI_STIG_FLAGSR_ERASEREADY(flag_sr))) + break; + } + + if (count >= CAD_QSPI_COMMAND_TIMEOUT) + ERROR("Timed out waiting for program and erase\n"); + + if ((program_only && CAD_QSPI_STIG_FLAGSR_PROGRAMERROR(flag_sr)) || + (!program_only && + CAD_QSPI_STIG_FLAGSR_ERASEERROR(flag_sr))) { + ERROR("Error programming/erasing flash\n"); + cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_CLFSR, 0); + return -1; + } + + return 0; +} +#endif + +int cad_qspi_indirect_read_start_bank(uint32_t flash_addr, uint32_t num_bytes) +{ + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDRDSTADDR, flash_addr); + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDRDCNT, num_bytes); + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDRD, + CAD_QSPI_INDRD_START | + CAD_QSPI_INDRD_IND_OPS_DONE); + + return 0; +} + + +int cad_qspi_indirect_write_start_bank(uint32_t flash_addr, + uint32_t num_bytes) +{ + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDWRSTADDR, flash_addr); + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDWRCNT, num_bytes); + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDWR, + CAD_QSPI_INDWR_START | + CAD_QSPI_INDWR_INDDONE); + + return 0; +} + +int cad_qspi_indirect_write_finish(void) +{ +#if CAD_QSPI_MICRON_N25Q_SUPPORT + return cad_qspi_n25q_wait_for_program_and_erase(1); +#else + return 0; +#endif + +} + +int cad_qspi_enable(void) +{ + int status; + + mmio_setbits_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, CAD_QSPI_CFG_ENABLE); + +#if CAD_QSPI_MICRON_N25Q_SUPPORT + status = cad_qspi_n25q_enable(); + if (status != 0) + return status; +#endif + return 0; +} + +int cad_qspi_enable_subsector_bank(uint32_t addr) +{ + int status = 0; + + status = cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WREN, 0); + if (status != 0) + return status; + + status = cad_qspi_stig_addr_cmd(CAD_QSPI_STIG_OPCODE_SUBSEC_ERASE, 0, + addr); + if (status != 0) + return status; + +#if CAD_QSPI_MICRON_N25Q_SUPPORT + status = cad_qspi_n25q_wait_for_program_and_erase(0); +#endif + return status; +} + +int cad_qspi_erase_subsector(uint32_t addr) +{ + int status = 0; + + status = cad_qspi_device_bank_select(addr >> 24); + if (status != 0) + return status; + + return cad_qspi_enable_subsector_bank(addr); +} + +int cad_qspi_erase_sector(uint32_t addr) +{ + int status = 0; + + status = cad_qspi_device_bank_select(addr >> 24); + if (status != 0) + return status; + + status = cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WREN, 0); + if (status != 0) + return status; + + status = cad_qspi_stig_addr_cmd(CAD_QSPI_STIG_OPCODE_SEC_ERASE, 0, + addr); + if (status != 0) + return status; + +#if CAD_QSPI_MICRON_N25Q_SUPPORT + status = cad_qspi_n25q_wait_for_program_and_erase(0); +#endif + return status; +} + +void cad_qspi_calibration(uint32_t dev_clk, uint32_t qspi_clk_mhz) +{ + int status; + uint32_t dev_sclk_mhz = 27; /*min value to get biggest 0xF div factor*/ + uint32_t data_cap_delay; + uint32_t sample_rdid; + uint32_t rdid; + uint32_t div_actual; + uint32_t div_bits; + int first_pass, last_pass; + + /*1. Set divider to bigger value (slowest SCLK) + *2. RDID and save the value + */ + div_actual = (qspi_clk_mhz + (dev_sclk_mhz - 1)) / dev_sclk_mhz; + div_bits = (((div_actual + 1) / 2) - 1); + status = cad_qspi_set_baudrate_div(0xf); + + status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, + 0, 3, &sample_rdid); + if (status != 0) + return; + + /*3. Set divider to the intended frequency + *4. Set the read delay = 0 + *5. RDID and check whether the value is same as item 2 + *6. Increase read delay and compared the value against item 2 + *7. Find the range of read delay that have same as + * item 2 and divide it to 2 + */ + div_actual = (qspi_clk_mhz + (dev_clk - 1)) / dev_clk; + div_bits = (((div_actual + 1) / 2) - 1); + status = cad_qspi_set_baudrate_div(div_bits); + if (status != 0) + return; + + data_cap_delay = 0; + first_pass = -1; + last_pass = -1; + + do { + if (status != 0) + break; + status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, 0, + 3, &rdid); + if (status != 0) + break; + if (rdid == sample_rdid) { + if (first_pass == -1) + first_pass = data_cap_delay; + else + last_pass = data_cap_delay; + } + + data_cap_delay++; + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_RDDATACAP, + CAD_QSPI_RDDATACAP_BYP(1) | + CAD_QSPI_RDDATACAP_DELAY(data_cap_delay)); + + } while (data_cap_delay < 0x10); + + if (first_pass > 0) { + int diff = first_pass - last_pass; + + data_cap_delay = first_pass + diff / 2; + } + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_RDDATACAP, + CAD_QSPI_RDDATACAP_BYP(1) | + CAD_QSPI_RDDATACAP_DELAY(data_cap_delay)); + status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, 0, 3, &rdid); + + if (status != 0) + return; +} + +int cad_qspi_int_disable(uint32_t mask) +{ + if (cad_qspi_idle() == 0) + return -1; + + if ((CAD_QSPI_INT_STATUS_ALL & mask) == 0) + return -1; + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_IRQMSK, mask); + return 0; +} + +void cad_qspi_set_chip_select(int cs) +{ + cad_qspi_cs = cs; +} + +int cad_qspi_init(uint32_t desired_clk_freq, uint32_t clk_phase, + uint32_t clk_pol, uint32_t csda, uint32_t csdads, + uint32_t cseot, uint32_t cssot, uint32_t rddatacap) +{ + int status = 0; + uint32_t qspi_desired_clk_freq; + uint32_t rdid = 0; + uint32_t cap_code; + + INFO("Initializing Qspi\n"); + + if (cad_qspi_idle() == 0) { + ERROR("device not idle"); + return -1; + } + + + status = cad_qspi_timing_config(clk_phase, clk_pol, csda, csdads, + cseot, cssot, rddatacap); + + if (status != 0) { + ERROR("config set timing failure\n"); + return status; + } + + mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_REMAPADDR, + CAD_QSPI_REMAPADDR_VALUE_SET(0)); + + status = cad_qspi_int_disable(CAD_QSPI_INT_STATUS_ALL); + if (status != 0) { + ERROR("failed disable\n"); + return status; + } + + cad_qspi_set_baudrate_div(0xf); + status = cad_qspi_enable(); + if (status != 0) { + ERROR("failed enable\n"); + return status; + } + + qspi_desired_clk_freq = 100; + cad_qspi_calibration(qspi_desired_clk_freq, 50000000); + + status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, 0, 3, + &rdid); + + if (status != 0) { + ERROR("Error reading RDID\n"); + return status; + } + + /* + * NOTE: The Size code seems to be a form of BCD (binary coded decimal). + * The first nibble is the 10's digit and the second nibble is the 1's + * digit in the number of bytes. + * + * Capacity ID samples: + * 0x15 : 16 Mb => 2 MiB => 1 << 21 ; BCD=15 + * 0x16 : 32 Mb => 4 MiB => 1 << 22 ; BCD=16 + * 0x17 : 64 Mb => 8 MiB => 1 << 23 ; BCD=17 + * 0x18 : 128 Mb => 16 MiB => 1 << 24 ; BCD=18 + * 0x19 : 256 Mb => 32 MiB => 1 << 25 ; BCD=19 + * 0x1a + * 0x1b + * 0x1c + * 0x1d + * 0x1e + * 0x1f + * 0x20 : 512 Mb => 64 MiB => 1 << 26 ; BCD=20 + * 0x21 : 1024 Mb => 128 MiB => 1 << 27 ; BCD=21 + */ + + cap_code = CAD_QSPI_STIG_RDID_CAPACITYID(rdid); + + if (!(((cap_code >> 4) > 0x9) || ((cap_code & 0xf) > 0x9))) { + uint32_t decoded_cap = ((cap_code >> 4) * 10) + + (cap_code & 0xf); + qspi_device_size = 1 << (decoded_cap + 6); + INFO("QSPI Capacity: %x\n\n", qspi_device_size); + + } else { + ERROR("Invalid CapacityID encountered: 0x%02x\n", + cap_code); + return -1; + } + + cad_qspi_configure_dev_size(S10_QSPI_ADDR_BYTES, + S10_QSPI_BYTES_PER_DEV, S10_BYTES_PER_BLOCK); + + INFO("Flash size: %d Bytes\n", qspi_device_size); + + return status; +} + +int cad_qspi_indirect_page_bound_write(uint32_t offset, + uint8_t *buffer, uint32_t len) +{ + int status = 0, i; + uint32_t write_count, write_capacity, *write_data, space, + write_fill_level, sram_partition; + + status = cad_qspi_indirect_write_start_bank(offset, len); + if (status != 0) + return status; + + write_count = 0; + sram_partition = CAD_QSPI_SRAMPART_ADDR(mmio_read_32(CAD_QSPI_OFFSET + + CAD_QSPI_SRAMPART)); + write_capacity = (uint32_t) CAD_QSPI_SRAM_FIFO_ENTRY_COUNT - + sram_partition; + + while (write_count < len) { + write_fill_level = CAD_QSPI_SRAMFILL_INDWRPART( + mmio_read_32(CAD_QSPI_OFFSET + + CAD_QSPI_SRAMFILL)); + space = LESS(write_capacity - write_fill_level, + (len - write_count) / sizeof(uint32_t)); + write_data = (uint32_t *)(buffer + write_count); + for (i = 0; i < space; ++i) + mmio_write_32(CAD_QSPIDATA_OFST, *write_data++); + + write_count += space * sizeof(uint32_t); + } + return cad_qspi_indirect_write_finish(); +} + +int cad_qspi_read_bank(uint8_t *buffer, uint32_t offset, uint32_t size) +{ + int status; + uint32_t read_count = 0, *read_data; + int level = 1, count = 0, i; + + status = cad_qspi_indirect_read_start_bank(offset, size); + + if (status != 0) + return status; + + while (read_count < size) { + do { + level = CAD_QSPI_SRAMFILL_INDRDPART( + mmio_read_32(CAD_QSPI_OFFSET + + CAD_QSPI_SRAMFILL)); + read_data = (uint32_t *)(buffer + read_count); + for (i = 0; i < level; ++i) + *read_data++ = mmio_read_32(CAD_QSPIDATA_OFST); + + read_count += level * sizeof(uint32_t); + count++; + } while (level > 0); + } + + return 0; +} + +int cad_qspi_write_bank(uint32_t offset, uint8_t *buffer, uint32_t size) +{ + int status = 0; + uint32_t page_offset = offset & (CAD_QSPI_PAGE_SIZE - 1); + uint32_t write_size = LESS(size, CAD_QSPI_PAGE_SIZE - page_offset); + + while (size) { + status = cad_qspi_indirect_page_bound_write(offset, buffer, + write_size); + if (status != 0) + break; + + offset += write_size; + buffer += write_size; + size -= write_size; + write_size = LESS(size, CAD_QSPI_PAGE_SIZE); + } + return status; +} + +int cad_qspi_read(void *buffer, uint32_t offset, uint32_t size) +{ + uint32_t bank_count, bank_addr, bank_offset, copy_len; + uint8_t *read_data; + int i, status; + + status = 0; + + if ((offset >= qspi_device_size) || + (offset + size - 1 >= qspi_device_size) || + (size == 0) || + ((long) ((int *)buffer) & 0x3) || + (offset & 0x3) || + (size & 0x3)) { + ERROR("Invalid read parameter"); + return -1; + } + + if (CAD_QSPI_INDRD_RD_STAT(mmio_read_32(CAD_QSPI_OFFSET + + CAD_QSPI_INDRD))) { + ERROR("Read in progress"); + return -1; + } + + /* + * bank_count : Number of bank(s) affected, including partial banks. + * bank_addr : Aligned address of the first bank, + * including partial bank. + * bank_ofst : The offset of the bank to read. + * Only used when reading the first bank. + */ + bank_count = CAD_QSPI_BANK_ADDR(offset + size - 1) - + CAD_QSPI_BANK_ADDR(offset) + 1; + bank_addr = offset & CAD_QSPI_BANK_ADDR_MSK; + bank_offset = offset & (CAD_QSPI_BANK_SIZE - 1); + + read_data = (uint8_t *)buffer; + + copy_len = LESS(size, CAD_QSPI_BANK_SIZE - bank_offset); + + for (i = 0; i < bank_count; ++i) { + status = cad_qspi_device_bank_select(CAD_QSPI_BANK_ADDR( + bank_addr)); + if (status != 0) + break; + status = cad_qspi_read_bank(read_data, bank_offset, copy_len); + if (status != 0) + break; + + bank_addr += CAD_QSPI_BANK_SIZE; + read_data += copy_len; + size -= copy_len; + bank_offset = 0; + copy_len = LESS(size, CAD_QSPI_BANK_SIZE); + } + + return status; +} + +int cad_qspi_erase(uint32_t offset, uint32_t size) +{ + int status = 0; + uint32_t subsector_offset = offset & (CAD_QSPI_SUBSECTOR_SIZE - 1); + uint32_t erase_size = LESS(size, + CAD_QSPI_SUBSECTOR_SIZE - subsector_offset); + + while (size) { + status = cad_qspi_erase_subsector(offset); + if (status != 0) + break; + + offset += erase_size; + size -= erase_size; + erase_size = LESS(size, CAD_QSPI_SUBSECTOR_SIZE); + } + return status; +} + +int cad_qspi_write(void *buffer, uint32_t offset, uint32_t size) +{ + int status, i; + uint32_t bank_count, bank_addr, bank_offset, copy_len; + uint8_t *write_data; + + status = 0; + + if ((offset >= qspi_device_size) || + (offset + size - 1 >= qspi_device_size) || + (size == 0) || + ((long)buffer & 0x3) || + (offset & 0x3) || + (size & 0x3)) + return -2; + + if (CAD_QSPI_INDWR_RDSTAT(mmio_read_32(CAD_QSPI_OFFSET + + CAD_QSPI_INDWR))) { + ERROR("QSPI Error: Write in progress\n"); + return -1; + } + + bank_count = CAD_QSPI_BANK_ADDR(offset + size - 1) - + CAD_QSPI_BANK_ADDR(offset) + 1; + bank_addr = offset & CAD_QSPI_BANK_ADDR_MSK; + bank_offset = offset & (CAD_QSPI_BANK_SIZE - 1); + + write_data = buffer; + + copy_len = LESS(size, CAD_QSPI_BANK_SIZE - bank_offset); + + for (i = 0; i < bank_count; ++i) { + status = cad_qspi_device_bank_select( + CAD_QSPI_BANK_ADDR(bank_addr)); + if (status != 0) + break; + + status = cad_qspi_write_bank(bank_offset, write_data, + copy_len); + if (status != 0) + break; + + bank_addr += CAD_QSPI_BANK_SIZE; + write_data += copy_len; + size -= copy_len; + bank_offset = 0; + + copy_len = LESS(size, CAD_QSPI_BANK_SIZE); + } + return status; +} + +int cad_qspi_update(void *Buffer, uint32_t offset, uint32_t size) +{ + int status = 0; + + status = cad_qspi_erase(offset, size); + if (status != 0) + return status; + + return cad_qspi_write(Buffer, offset, size); +} + +void cad_qspi_reset(void) +{ + cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_RESET_EN, 0); + cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_RESET_MEM, 0); +} + diff --git a/plat/intel/soc/common/drivers/qspi/cadence_qspi.h b/plat/intel/soc/common/drivers/qspi/cadence_qspi.h new file mode 100644 index 0000000..3906a1a --- /dev/null +++ b/plat/intel/soc/common/drivers/qspi/cadence_qspi.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CAD_QSPI_H +#define CAD_QSPI_H + +#define CAD_QSPI_MICRON_N25Q_SUPPORT 1 + +#define CAD_QSPI_OFFSET 0xff8d2000 + +#define CAD_INVALID -1 +#define CAD_QSPI_ERROR -2 + +#define CAD_QSPI_ADDR_FASTREAD 0 +#define CAD_QSPI_ADDR_FASTREAD_DUAL_IO 1 +#define CAD_QSPI_ADDR_FASTREAD_QUAD_IO 2 +#define CAT_QSPI_ADDR_SINGLE_IO 0 +#define CAT_QSPI_ADDR_DUAL_IO 1 +#define CAT_QSPI_ADDR_QUAD_IO 2 + +#define CAD_QSPI_BANK_ADDR(x) ((x) >> 24) +#define CAD_QSPI_BANK_ADDR_MSK 0xff000000 + +#define CAD_QSPI_COMMAND_TIMEOUT 0x10000000 + +#define CAD_QSPI_CFG 0x0 +#define CAD_QSPI_CFG_BAUDDIV_MSK 0xff87ffff +#define CAD_QSPI_CFG_BAUDDIV(x) (((x) << 19) & 0x780000) +#define CAD_QSPI_CFG_CS_MSK ~0x3c00 +#define CAD_QSPI_CFG_CS(x) (((x) << 11)) +#define CAD_QSPI_CFG_ENABLE (1 << 0) +#define CAD_QSPI_CFG_ENDMA_CLR_MSK 0xffff7fff +#define CAD_QSPI_CFG_IDLE (1 << 31) +#define CAD_QSPI_CFG_SELCLKPHASE_CLR_MSK 0xfffffffb +#define CAD_QSPI_CFG_SELCLKPOL_CLR_MSK 0xfffffffd + +#define CAD_QSPIDATA_OFST 0xff900000 + +#define CAD_QSPI_DELAY 0xc +#define CAD_QSPI_DELAY_CSSOT(x) (((x) & 0xff) << 0) +#define CAD_QSPI_DELAY_CSEOT(x) (((x) & 0xff) << 8) +#define CAD_QSPI_DELAY_CSDADS(x) (((x) & 0xff) << 16) +#define CAD_QSPI_DELAY_CSDA(x) (((x) & 0xff) << 24) + +#define CAD_QSPI_DEVSZ 0x14 +#define CAD_QSPI_DEVSZ_ADDR_BYTES(x) ((x) << 0) +#define CAD_QSPI_DEVSZ_BYTES_PER_PAGE(x) ((x) << 4) +#define CAD_QSPI_DEVSZ_BYTES_PER_BLOCK(x) ((x) << 16) + +#define CAD_QSPI_DEVWR 0x8 +#define CAD_QSPI_DEVRD 0x4 +#define CAD_QSPI_DEV_OPCODE(x) (((x) & 0xff) << 0) +#define CAD_QSPI_DEV_INST_TYPE(x) (((x) & 0x03) << 8) +#define CAD_QSPI_DEV_ADDR_TYPE(x) (((x) & 0x03) << 12) +#define CAD_QSPI_DEV_DATA_TYPE(x) (((x) & 0x03) << 16) +#define CAD_QSPI_DEV_MODE_BIT(x) (((x) & 0x01) << 20) +#define CAD_QSPI_DEV_DUMMY_CLK_CYCLE(x) (((x) & 0x0f) << 24) + +#define CAD_QSPI_FLASHCMD 0x90 +#define CAD_QSPI_FLASHCMD_ADDR 0x94 +#define CAD_QSPI_FLASHCMD_EXECUTE 0x1 +#define CAD_QSPI_FLASHCMD_EXECUTE_STAT 0x2 +#define CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX 5 +#define CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES(x) (((x) << 7) & 0x000f80) +#define CAD_QSPI_FLASHCMD_OPCODE(x) (((x) & 0xff) << 24) +#define CAD_QSPI_FLASHCMD_ENRDDATA(x) (((x) & 1) << 23) +#define CAD_QSPI_FLASHCMD_NUMRDDATABYTES(x) (((x) & 0xf) << 20) +#define CAD_QSPI_FLASHCMD_ENCMDADDR(x) (((x) & 1) << 19) +#define CAD_QSPI_FLASHCMD_ENMODEBIT(x) (((x) & 1) << 18) +#define CAD_QSPI_FLASHCMD_NUMADDRBYTES(x) (((x) & 0x3) << 16) +#define CAD_QSPI_FLASHCMD_ENWRDATA(x) (((x) & 1) << 15) +#define CAD_QSPI_FLASHCMD_NUMWRDATABYTES(x) (((x) & 0x7) << 12) +#define CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(x) (((x) & 0x1f) << 7) +#define CAD_QSPI_FLASHCMD_RDDATA0 0xa0 +#define CAD_QSPI_FLASHCMD_RDDATA1 0xa4 +#define CAD_QSPI_FLASHCMD_WRDATA0 0xa8 +#define CAD_QSPI_FLASHCMD_WRDATA1 0xac + +#define CAD_QSPI_RDDATACAP 0x10 +#define CAD_QSPI_RDDATACAP_BYP(x) (((x) & 1) << 0) +#define CAD_QSPI_RDDATACAP_DELAY(x) (((x) & 0xf) << 1) + +#define CAD_QSPI_REMAPADDR 0x24 +#define CAD_QSPI_REMAPADDR_VALUE_SET(x) (((x) & 0xffffffff) << 0) + +#define CAD_QSPI_SRAMPART 0x18 +#define CAD_QSPI_SRAMFILL 0x2c +#define CAD_QSPI_SRAMPART_ADDR(x) (((x) >> 0) & 0x3ff) +#define CAD_QSPI_SRAM_FIFO_ENTRY_COUNT (512 / sizeof(uint32_t)) +#define CAD_QSPI_SRAMFILL_INDWRPART(x) (((x) >> 16) & 0x00ffff) +#define CAD_QSPI_SRAMFILL_INDRDPART(x) (((x) >> 0) & 0x00ffff) + +#define CAD_QSPI_SELCLKPHASE(x) (((x) & 1) << 2) +#define CAD_QSPI_SELCLKPOL(x) (((x) & 1) << 1) + +#define CAD_QSPI_STIG_FLAGSR_PROGRAMREADY(x) (((x) >> 7) & 1) +#define CAD_QSPI_STIG_FLAGSR_ERASEREADY(x) (((x) >> 7) & 1) +#define CAD_QSPI_STIG_FLAGSR_ERASEERROR(x) (((x) >> 5) & 1) +#define CAD_QSPI_STIG_FLAGSR_PROGRAMERROR(x) (((x) >> 4) & 1) +#define CAD_QSPI_STIG_OPCODE_CLFSR 0x50 +#define CAD_QSPI_STIG_OPCODE_RDID 0x9f +#define CAD_QSPI_STIG_OPCODE_WRDIS 0x4 +#define CAD_QSPI_STIG_OPCODE_WREN 0x6 +#define CAD_QSPI_STIG_OPCODE_SUBSEC_ERASE 0x20 +#define CAD_QSPI_STIG_OPCODE_SEC_ERASE 0xd8 +#define CAD_QSPI_STIG_OPCODE_WREN_EXT_REG 0xc5 +#define CAD_QSPI_STIG_OPCODE_DIE_ERASE 0xc4 +#define CAD_QSPI_STIG_OPCODE_BULK_ERASE 0xc7 +#define CAD_QSPI_STIG_OPCODE_RDSR 0x5 +#define CAD_QSPI_STIG_OPCODE_RDFLGSR 0x70 +#define CAD_QSPI_STIG_OPCODE_RESET_EN 0x66 +#define CAD_QSPI_STIG_OPCODE_RESET_MEM 0x99 +#define CAD_QSPI_STIG_RDID_CAPACITYID(x) (((x) >> 16) & 0xff) +#define CAD_QSPI_STIG_SR_BUSY(x) (((x) >> 0) & 1) + + +#define CAD_QSPI_INST_SINGLE 0 +#define CAD_QSPI_INST_DUAL 1 +#define CAD_QSPI_INST_QUAD 2 + +#define CAD_QSPI_INDRDSTADDR 0x68 +#define CAD_QSPI_INDRDCNT 0x6c +#define CAD_QSPI_INDRD 0x60 +#define CAD_QSPI_INDRD_RD_STAT(x) (((x) >> 2) & 1) +#define CAD_QSPI_INDRD_START 1 +#define CAD_QSPI_INDRD_IND_OPS_DONE 0x20 + +#define CAD_QSPI_INDWR 0x70 +#define CAD_QSPI_INDWR_RDSTAT(x) (((x) >> 2) & 1) +#define CAD_QSPI_INDWRSTADDR 0x78 +#define CAD_QSPI_INDWRCNT 0x7c +#define CAD_QSPI_INDWR 0x70 +#define CAD_QSPI_INDWR_START 0x1 +#define CAD_QSPI_INDWR_INDDONE 0x20 + +#define CAD_QSPI_INT_STATUS_ALL 0x0000ffff + +#define CAD_QSPI_N25Q_DIE_SIZE 0x02000000 +#define CAD_QSPI_BANK_SIZE 0x01000000 +#define CAD_QSPI_PAGE_SIZE 0x00000100 + +#define CAD_QSPI_IRQMSK 0x44 + +#define CAD_QSPI_SUBSECTOR_SIZE 0x1000 + +#define S10_QSPI_ADDR_BYTES 2 +#define S10_QSPI_BYTES_PER_DEV 256 +#define S10_BYTES_PER_BLOCK 16 + +#define QSPI_FAST_READ 0xb + +// QSPI CONFIGURATIONS + +#define QSPI_CONFIG_CPOL 1 +#define QSPI_CONFIG_CPHA 1 + +#define QSPI_CONFIG_CSSOT 0x14 +#define QSPI_CONFIG_CSEOT 0x14 +#define QSPI_CONFIG_CSDADS 0xff +#define QSPI_CONFIG_CSDA 0xc8 + +int cad_qspi_init(uint32_t desired_clk_freq, uint32_t clk_phase, + uint32_t clk_pol, uint32_t csda, uint32_t csdads, + uint32_t cseot, uint32_t cssot, uint32_t rddatacap); +void cad_qspi_set_chip_select(int cs); +int cad_qspi_erase(uint32_t offset, uint32_t size); +int cad_qspi_write(void *buffer, uint32_t offset, uint32_t size); +int cad_qspi_read(void *buffer, uint32_t offset, uint32_t size); +int cad_qspi_update(void *buffer, uint32_t offset, uint32_t size); + +#endif + diff --git a/plat/intel/soc/common/drivers/wdt/watchdog.c b/plat/intel/soc/common/drivers/wdt/watchdog.c new file mode 100644 index 0000000..b4dbe5f --- /dev/null +++ b/plat/intel/soc/common/drivers/wdt/watchdog.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "watchdog.h" + + +/* Reset watchdog timer */ +void watchdog_sw_rst(void) +{ + mmio_write_32(WDT_CRR, WDT_SW_RST); +} + +/* Print component information */ +void watchdog_info(void) +{ + INFO("Component Type : %x\r\n", mmio_read_32(WDT_COMP_VERSION)); + INFO("Component Version : %x\r\n", mmio_read_32(WDT_COMP_TYPE)); +} + +/* Check watchdog current status */ +void watchdog_status(void) +{ + if (mmio_read_32(WDT_CR) & 1) { + INFO("Watchdog Timer in currently enabled\n"); + INFO("Current Counter : 0x%x\r\n", mmio_read_32(WDT_CCVR)); + } else { + INFO("Watchdog Timer in currently disabled\n"); + } +} + +/* Initialize & enable watchdog */ +void watchdog_init(int watchdog_clk) +{ + uint8_t cycles_i = 0; + uint32_t wdt_cycles = WDT_MIN_CYCLES; + uint32_t top_init_cycles = WDT_PERIOD * watchdog_clk; + + while ((cycles_i < 15) && (wdt_cycles < top_init_cycles)) { + wdt_cycles = (wdt_cycles << 1); + cycles_i++; + } + + mmio_write_32(WDT_TORR, (cycles_i << 4) | cycles_i); + + watchdog_enable(); +} + +void watchdog_enable(void) +{ + mmio_write_32(WDT_CR, WDT_CR_RMOD|WDT_CR_EN); +} diff --git a/plat/intel/soc/common/drivers/wdt/watchdog.h b/plat/intel/soc/common/drivers/wdt/watchdog.h new file mode 100644 index 0000000..9410242 --- /dev/null +++ b/plat/intel/soc/common/drivers/wdt/watchdog.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CAD_WATCHDOG_H +#define CAD_WATCHDOG_H + +#define WDT_BASE (0xFFD00200) +#define WDT_REG_SIZE_OFFSET (0x4) +#define WDT_MIN_CYCLES (65536) +#define WDT_PERIOD (20) + +#define WDT_CR (WDT_BASE + 0x0) +#define WDT_TORR (WDT_BASE + 0x4) + +#define WDT_CRR (WDT_BASE + 0xC) + +#define WDT_CCVR (WDT_BASE + 0x8) +#define WDT_STAT (WDT_BASE + 0x10) +#define WDT_EOI (WDT_BASE + 0x14) + +#define WDT_COMP_PARAM_1 (WDT_BASE + 0xF4) +#define WDT_COMP_VERSION (WDT_BASE + 0xF8) +#define WDT_COMP_TYPE (WDT_BASE + 0XFC) + +#define WDT_CR_RMOD (0x0) +#define WDT_CR_EN (0x1) + +#define WDT_SW_RST (0x76) + + +void watchdog_init(int watchdog_clk); +void watchdog_enable(void); +void watchdog_info(void); +void watchdog_status(void); +void watchdog_sw_rst(void); + +#endif diff --git a/plat/intel/soc/stratix10/bl2_plat_setup.c b/plat/intel/soc/stratix10/bl2_plat_setup.c index 58e8c02..7830162 100644 --- a/plat/intel/soc/stratix10/bl2_plat_setup.c +++ b/plat/intel/soc/stratix10/bl2_plat_setup.c @@ -31,8 +31,8 @@ #include "s10_pinmux.h" #include "aarch64/stratix10_private.h" #include "include/s10_mailbox.h" -#include "drivers/qspi/cadence_qspi.h" -#include "drivers/wdt/watchdog.h" +#include "qspi/cadence_qspi.h" +#include "wdt/watchdog.h" const mmap_region_t plat_stratix10_mmap[] = { diff --git a/plat/intel/soc/stratix10/drivers/qspi/cadence_qspi.c b/plat/intel/soc/stratix10/drivers/qspi/cadence_qspi.c deleted file mode 100644 index 506a633..0000000 --- a/plat/intel/soc/stratix10/drivers/qspi/cadence_qspi.c +++ /dev/null @@ -1,824 +0,0 @@ -/* - * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include -#include -#include -#include -#include - -#include "cadence_qspi.h" -#include - -#define LESS(a, b) (((a) < (b)) ? (a) : (b)) -#define MORE(a, b) (((a) > (b)) ? (a) : (b)) - - -uint32_t qspi_device_size; -int cad_qspi_cs; - -int cad_qspi_idle(void) -{ - return (mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG) - & CAD_QSPI_CFG_IDLE) >> 31; -} - -int cad_qspi_set_baudrate_div(uint32_t div) -{ - if (div > 0xf) - return CAD_INVALID; - - mmio_clrsetbits_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, - ~CAD_QSPI_CFG_BAUDDIV_MSK, - CAD_QSPI_CFG_BAUDDIV(div)); - - return 0; -} - -int cad_qspi_configure_dev_size(uint32_t addr_bytes, - uint32_t bytes_per_dev, uint32_t bytes_per_block) -{ - - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DEVSZ, - CAD_QSPI_DEVSZ_ADDR_BYTES(addr_bytes) | - CAD_QSPI_DEVSZ_BYTES_PER_PAGE(bytes_per_dev) | - CAD_QSPI_DEVSZ_BYTES_PER_BLOCK(bytes_per_block)); - return 0; -} - -int cad_qspi_set_read_config(uint32_t opcode, uint32_t instr_type, - uint32_t addr_type, uint32_t data_type, - uint32_t mode_bit, uint32_t dummy_clk_cycle) -{ - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DEVRD, - CAD_QSPI_DEV_OPCODE(opcode) | - CAD_QSPI_DEV_INST_TYPE(instr_type) | - CAD_QSPI_DEV_ADDR_TYPE(addr_type) | - CAD_QSPI_DEV_DATA_TYPE(data_type) | - CAD_QSPI_DEV_MODE_BIT(mode_bit) | - CAD_QSPI_DEV_DUMMY_CLK_CYCLE(dummy_clk_cycle)); - - return 0; -} - -int cat_qspi_set_write_config(uint32_t addr_type, uint32_t data_type, - uint32_t mode_bit, uint32_t dummy_clk_cycle) -{ - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DEVWR, - CAD_QSPI_DEV_ADDR_TYPE(addr_type) | - CAD_QSPI_DEV_DATA_TYPE(data_type) | - CAD_QSPI_DEV_MODE_BIT(mode_bit) | - CAD_QSPI_DEV_DUMMY_CLK_CYCLE(dummy_clk_cycle)); - - return 0; -} - -int cad_qspi_timing_config(uint32_t clkphase, uint32_t clkpol, uint32_t csda, - uint32_t csdads, uint32_t cseot, uint32_t cssot, - uint32_t rddatacap) -{ - uint32_t cfg = mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG); - - cfg &= CAD_QSPI_CFG_SELCLKPHASE_CLR_MSK & - CAD_QSPI_CFG_SELCLKPOL_CLR_MSK; - cfg |= CAD_QSPI_SELCLKPHASE(clkphase) | CAD_QSPI_SELCLKPOL(clkpol); - - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, cfg); - - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DELAY, - CAD_QSPI_DELAY_CSSOT(cssot) | CAD_QSPI_DELAY_CSEOT(cseot) | - CAD_QSPI_DELAY_CSDADS(csdads) | CAD_QSPI_DELAY_CSDA(csda)); - - return 0; -} - -int cad_qspi_stig_cmd_helper(int cs, uint32_t cmd) -{ - uint32_t count = 0; - - /* chip select */ - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, - (mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG) - & CAD_QSPI_CFG_CS_MSK) | CAD_QSPI_CFG_CS(cs)); - - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD, cmd); - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD, - cmd | CAD_QSPI_FLASHCMD_EXECUTE); - - do { - uint32_t reg = mmio_read_32(CAD_QSPI_OFFSET + - CAD_QSPI_FLASHCMD); - if (!(reg & CAD_QSPI_FLASHCMD_EXECUTE_STAT)) - break; - count++; - } while (count < CAD_QSPI_COMMAND_TIMEOUT); - - if (count >= CAD_QSPI_COMMAND_TIMEOUT) { - ERROR("Error sending QSPI command %x, timed out\n", - cmd); - return CAD_QSPI_ERROR; - } - - return 0; -} - -int cad_qspi_stig_cmd(uint32_t opcode, uint32_t dummy) -{ - if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) { - ERROR("Faulty dummy bytes\n"); - return -1; - } - - return cad_qspi_stig_cmd_helper(cad_qspi_cs, - CAD_QSPI_FLASHCMD_OPCODE(opcode) | - CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES(dummy)); -} - -int cad_qspi_stig_read_cmd(uint32_t opcode, uint32_t dummy, uint32_t num_bytes, - uint32_t *output) -{ - if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) { - ERROR("Faulty dummy byes\n"); - return -1; - } - - if ((num_bytes > 8) || (num_bytes == 0)) - return -1; - - uint32_t cmd = - CAD_QSPI_FLASHCMD_OPCODE(opcode) | - CAD_QSPI_FLASHCMD_ENRDDATA(1) | - CAD_QSPI_FLASHCMD_NUMRDDATABYTES(num_bytes - 1) | - CAD_QSPI_FLASHCMD_ENCMDADDR(0) | - CAD_QSPI_FLASHCMD_ENMODEBIT(0) | - CAD_QSPI_FLASHCMD_NUMADDRBYTES(0) | - CAD_QSPI_FLASHCMD_ENWRDATA(0) | - CAD_QSPI_FLASHCMD_NUMWRDATABYTES(0) | - CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(dummy); - - if (cad_qspi_stig_cmd_helper(cad_qspi_cs, cmd)) { - ERROR("failed to send stig cmd"); - return -1; - } - - output[0] = mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_RDDATA0); - - if (num_bytes > 4) { - output[1] = mmio_read_32(CAD_QSPI_OFFSET + - CAD_QSPI_FLASHCMD_RDDATA1); - } - - return 0; -} - -int cad_qspi_stig_wr_cmd(uint32_t opcode, uint32_t dummy, uint32_t num_bytes, - uint32_t *input) -{ - if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) { - ERROR("Faulty dummy byes\n"); - return -1; - } - - if ((num_bytes > 8) || (num_bytes == 0)) - return -1; - - uint32_t cmd = CAD_QSPI_FLASHCMD_OPCODE(opcode) | - CAD_QSPI_FLASHCMD_ENRDDATA(0) | - CAD_QSPI_FLASHCMD_NUMRDDATABYTES(0) | - CAD_QSPI_FLASHCMD_ENCMDADDR(0) | - CAD_QSPI_FLASHCMD_ENMODEBIT(0) | - CAD_QSPI_FLASHCMD_NUMADDRBYTES(0) | - CAD_QSPI_FLASHCMD_ENWRDATA(1) | - CAD_QSPI_FLASHCMD_NUMWRDATABYTES(num_bytes - 1) | - CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(dummy); - - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_WRDATA0, input[0]); - - if (num_bytes > 4) - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_WRDATA1, - input[1]); - - return cad_qspi_stig_cmd_helper(cad_qspi_cs, cmd); -} - -int cad_qspi_stig_addr_cmd(uint32_t opcode, uint32_t dummy, uint32_t addr) -{ - uint32_t cmd; - - if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) - return -1; - - cmd = CAD_QSPI_FLASHCMD_OPCODE(opcode) | - CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(dummy) | - CAD_QSPI_FLASHCMD_ENCMDADDR(1) | - CAD_QSPI_FLASHCMD_NUMADDRBYTES(2); - - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_ADDR, addr); - - return cad_qspi_stig_cmd_helper(cad_qspi_cs, cmd); -} - -int cad_qspi_device_bank_select(uint32_t bank) -{ - int status = 0; - - status = cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WREN, 0); - if (status != 0) - return status; - - status = cad_qspi_stig_wr_cmd(CAD_QSPI_STIG_OPCODE_WREN_EXT_REG, - 0, 1, &bank); - if (status != 0) - return status; - - return cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WRDIS, 0); -} - -int cad_qspi_device_status(uint32_t *status) -{ - return cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDSR, 0, 1, status); -} - -#if CAD_QSPI_MICRON_N25Q_SUPPORT -int cad_qspi_n25q_enable(void) -{ - cad_qspi_set_read_config(QSPI_FAST_READ, CAD_QSPI_INST_SINGLE, - CAD_QSPI_ADDR_FASTREAD, CAT_QSPI_ADDR_SINGLE_IO, 1, - 0); - return 0; -} - -int cad_qspi_n25q_wait_for_program_and_erase(int program_only) -{ - uint32_t status, flag_sr; - int count = 0; - - while (count < CAD_QSPI_COMMAND_TIMEOUT) { - status = cad_qspi_device_status(&status); - if (status != 0) { - ERROR("Error getting device status\n"); - return -1; - } - if (!CAD_QSPI_STIG_SR_BUSY(status)) - break; - count++; - } - - if (count >= CAD_QSPI_COMMAND_TIMEOUT) { - ERROR("Timed out waiting for idle\n"); - return -1; - } - - count = 0; - - while (count < CAD_QSPI_COMMAND_TIMEOUT) { - status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDFLGSR, - 0, 1, &flag_sr); - if (status != 0) { - ERROR("Error waiting program and erase.\n"); - return status; - } - - if ((program_only && - CAD_QSPI_STIG_FLAGSR_PROGRAMREADY(flag_sr)) || - (!program_only && - CAD_QSPI_STIG_FLAGSR_ERASEREADY(flag_sr))) - break; - } - - if (count >= CAD_QSPI_COMMAND_TIMEOUT) - ERROR("Timed out waiting for program and erase\n"); - - if ((program_only && CAD_QSPI_STIG_FLAGSR_PROGRAMERROR(flag_sr)) || - (!program_only && - CAD_QSPI_STIG_FLAGSR_ERASEERROR(flag_sr))) { - ERROR("Error programming/erasing flash\n"); - cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_CLFSR, 0); - return -1; - } - - return 0; -} -#endif - -int cad_qspi_indirect_read_start_bank(uint32_t flash_addr, uint32_t num_bytes) -{ - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDRDSTADDR, flash_addr); - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDRDCNT, num_bytes); - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDRD, - CAD_QSPI_INDRD_START | - CAD_QSPI_INDRD_IND_OPS_DONE); - - return 0; -} - - -int cad_qspi_indirect_write_start_bank(uint32_t flash_addr, - uint32_t num_bytes) -{ - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDWRSTADDR, flash_addr); - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDWRCNT, num_bytes); - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDWR, - CAD_QSPI_INDWR_START | - CAD_QSPI_INDWR_INDDONE); - - return 0; -} - -int cad_qspi_indirect_write_finish(void) -{ -#if CAD_QSPI_MICRON_N25Q_SUPPORT - return cad_qspi_n25q_wait_for_program_and_erase(1); -#else - return 0; -#endif - -} - -int cad_qspi_enable(void) -{ - int status; - - mmio_setbits_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, CAD_QSPI_CFG_ENABLE); - -#if CAD_QSPI_MICRON_N25Q_SUPPORT - status = cad_qspi_n25q_enable(); - if (status != 0) - return status; -#endif - return 0; -} - -int cad_qspi_enable_subsector_bank(uint32_t addr) -{ - int status = 0; - - status = cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WREN, 0); - if (status != 0) - return status; - - status = cad_qspi_stig_addr_cmd(CAD_QSPI_STIG_OPCODE_SUBSEC_ERASE, 0, - addr); - if (status != 0) - return status; - -#if CAD_QSPI_MICRON_N25Q_SUPPORT - status = cad_qspi_n25q_wait_for_program_and_erase(0); -#endif - return status; -} - -int cad_qspi_erase_subsector(uint32_t addr) -{ - int status = 0; - - status = cad_qspi_device_bank_select(addr >> 24); - if (status != 0) - return status; - - return cad_qspi_enable_subsector_bank(addr); -} - -int cad_qspi_erase_sector(uint32_t addr) -{ - int status = 0; - - status = cad_qspi_device_bank_select(addr >> 24); - if (status != 0) - return status; - - status = cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WREN, 0); - if (status != 0) - return status; - - status = cad_qspi_stig_addr_cmd(CAD_QSPI_STIG_OPCODE_SEC_ERASE, 0, - addr); - if (status != 0) - return status; - -#if CAD_QSPI_MICRON_N25Q_SUPPORT - status = cad_qspi_n25q_wait_for_program_and_erase(0); -#endif - return status; -} - -void cad_qspi_calibration(uint32_t dev_clk, uint32_t qspi_clk_mhz) -{ - int status; - uint32_t dev_sclk_mhz = 27; /*min value to get biggest 0xF div factor*/ - uint32_t data_cap_delay; - uint32_t sample_rdid; - uint32_t rdid; - uint32_t div_actual; - uint32_t div_bits; - int first_pass, last_pass; - - /*1. Set divider to bigger value (slowest SCLK) - *2. RDID and save the value - */ - div_actual = (qspi_clk_mhz + (dev_sclk_mhz - 1)) / dev_sclk_mhz; - div_bits = (((div_actual + 1) / 2) - 1); - status = cad_qspi_set_baudrate_div(0xf); - - status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, - 0, 3, &sample_rdid); - if (status != 0) - return; - - /*3. Set divider to the intended frequency - *4. Set the read delay = 0 - *5. RDID and check whether the value is same as item 2 - *6. Increase read delay and compared the value against item 2 - *7. Find the range of read delay that have same as - * item 2 and divide it to 2 - */ - div_actual = (qspi_clk_mhz + (dev_clk - 1)) / dev_clk; - div_bits = (((div_actual + 1) / 2) - 1); - status = cad_qspi_set_baudrate_div(div_bits); - if (status != 0) - return; - - data_cap_delay = 0; - first_pass = -1; - last_pass = -1; - - do { - if (status != 0) - break; - status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, 0, - 3, &rdid); - if (status != 0) - break; - if (rdid == sample_rdid) { - if (first_pass == -1) - first_pass = data_cap_delay; - else - last_pass = data_cap_delay; - } - - data_cap_delay++; - - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_RDDATACAP, - CAD_QSPI_RDDATACAP_BYP(1) | - CAD_QSPI_RDDATACAP_DELAY(data_cap_delay)); - - } while (data_cap_delay < 0x10); - - if (first_pass > 0) { - int diff = first_pass - last_pass; - - data_cap_delay = first_pass + diff / 2; - } - - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_RDDATACAP, - CAD_QSPI_RDDATACAP_BYP(1) | - CAD_QSPI_RDDATACAP_DELAY(data_cap_delay)); - status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, 0, 3, &rdid); - - if (status != 0) - return; -} - -int cad_qspi_int_disable(uint32_t mask) -{ - if (cad_qspi_idle() == 0) - return -1; - - if ((CAD_QSPI_INT_STATUS_ALL & mask) == 0) - return -1; - - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_IRQMSK, mask); - return 0; -} - -void cad_qspi_set_chip_select(int cs) -{ - cad_qspi_cs = cs; -} - -int cad_qspi_init(uint32_t desired_clk_freq, uint32_t clk_phase, - uint32_t clk_pol, uint32_t csda, uint32_t csdads, - uint32_t cseot, uint32_t cssot, uint32_t rddatacap) -{ - int status = 0; - uint32_t qspi_desired_clk_freq; - uint32_t rdid = 0; - uint32_t cap_code; - - INFO("Initializing Qspi\n"); - - if (cad_qspi_idle() == 0) { - ERROR("device not idle"); - return -1; - } - - - status = cad_qspi_timing_config(clk_phase, clk_pol, csda, csdads, - cseot, cssot, rddatacap); - - if (status != 0) { - ERROR("config set timing failure\n"); - return status; - } - - mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_REMAPADDR, - CAD_QSPI_REMAPADDR_VALUE_SET(0)); - - status = cad_qspi_int_disable(CAD_QSPI_INT_STATUS_ALL); - if (status != 0) { - ERROR("failed disable\n"); - return status; - } - - cad_qspi_set_baudrate_div(0xf); - status = cad_qspi_enable(); - if (status != 0) { - ERROR("failed enable\n"); - return status; - } - - qspi_desired_clk_freq = 100; - cad_qspi_calibration(qspi_desired_clk_freq, 50000000); - - status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, 0, 3, - &rdid); - - if (status != 0) { - ERROR("Error reading RDID\n"); - return status; - } - - /* - * NOTE: The Size code seems to be a form of BCD (binary coded decimal). - * The first nibble is the 10's digit and the second nibble is the 1's - * digit in the number of bytes. - * - * Capacity ID samples: - * 0x15 : 16 Mb => 2 MiB => 1 << 21 ; BCD=15 - * 0x16 : 32 Mb => 4 MiB => 1 << 22 ; BCD=16 - * 0x17 : 64 Mb => 8 MiB => 1 << 23 ; BCD=17 - * 0x18 : 128 Mb => 16 MiB => 1 << 24 ; BCD=18 - * 0x19 : 256 Mb => 32 MiB => 1 << 25 ; BCD=19 - * 0x1a - * 0x1b - * 0x1c - * 0x1d - * 0x1e - * 0x1f - * 0x20 : 512 Mb => 64 MiB => 1 << 26 ; BCD=20 - * 0x21 : 1024 Mb => 128 MiB => 1 << 27 ; BCD=21 - */ - - cap_code = CAD_QSPI_STIG_RDID_CAPACITYID(rdid); - - if (!(((cap_code >> 4) > 0x9) || ((cap_code & 0xf) > 0x9))) { - uint32_t decoded_cap = ((cap_code >> 4) * 10) + - (cap_code & 0xf); - qspi_device_size = 1 << (decoded_cap + 6); - INFO("QSPI Capacity: %x\n\n", qspi_device_size); - - } else { - ERROR("Invalid CapacityID encountered: 0x%02x\n", - cap_code); - return -1; - } - - cad_qspi_configure_dev_size(S10_QSPI_ADDR_BYTES, - S10_QSPI_BYTES_PER_DEV, S10_BYTES_PER_BLOCK); - - INFO("Flash size: %d Bytes\n", qspi_device_size); - - return status; -} - -int cad_qspi_indirect_page_bound_write(uint32_t offset, - uint8_t *buffer, uint32_t len) -{ - int status = 0, i; - uint32_t write_count, write_capacity, *write_data, space, - write_fill_level, sram_partition; - - status = cad_qspi_indirect_write_start_bank(offset, len); - if (status != 0) - return status; - - write_count = 0; - sram_partition = CAD_QSPI_SRAMPART_ADDR(mmio_read_32(CAD_QSPI_OFFSET + - CAD_QSPI_SRAMPART)); - write_capacity = (uint32_t) CAD_QSPI_SRAM_FIFO_ENTRY_COUNT - - sram_partition; - - while (write_count < len) { - write_fill_level = CAD_QSPI_SRAMFILL_INDWRPART( - mmio_read_32(CAD_QSPI_OFFSET + - CAD_QSPI_SRAMFILL)); - space = LESS(write_capacity - write_fill_level, - (len - write_count) / sizeof(uint32_t)); - write_data = (uint32_t *)(buffer + write_count); - for (i = 0; i < space; ++i) - mmio_write_32(CAD_QSPIDATA_OFST, *write_data++); - - write_count += space * sizeof(uint32_t); - } - return cad_qspi_indirect_write_finish(); -} - -int cad_qspi_read_bank(uint8_t *buffer, uint32_t offset, uint32_t size) -{ - int status; - uint32_t read_count = 0, *read_data; - int level = 1, count = 0, i; - - status = cad_qspi_indirect_read_start_bank(offset, size); - - if (status != 0) - return status; - - while (read_count < size) { - do { - level = CAD_QSPI_SRAMFILL_INDRDPART( - mmio_read_32(CAD_QSPI_OFFSET + - CAD_QSPI_SRAMFILL)); - read_data = (uint32_t *)(buffer + read_count); - for (i = 0; i < level; ++i) - *read_data++ = mmio_read_32(CAD_QSPIDATA_OFST); - - read_count += level * sizeof(uint32_t); - count++; - } while (level > 0); - } - - return 0; -} - -int cad_qspi_write_bank(uint32_t offset, uint8_t *buffer, uint32_t size) -{ - int status = 0; - uint32_t page_offset = offset & (CAD_QSPI_PAGE_SIZE - 1); - uint32_t write_size = LESS(size, CAD_QSPI_PAGE_SIZE - page_offset); - - while (size) { - status = cad_qspi_indirect_page_bound_write(offset, buffer, - write_size); - if (status != 0) - break; - - offset += write_size; - buffer += write_size; - size -= write_size; - write_size = LESS(size, CAD_QSPI_PAGE_SIZE); - } - return status; -} - -int cad_qspi_read(void *buffer, uint32_t offset, uint32_t size) -{ - uint32_t bank_count, bank_addr, bank_offset, copy_len; - uint8_t *read_data; - int i, status; - - status = 0; - - if ((offset >= qspi_device_size) || - (offset + size - 1 >= qspi_device_size) || - (size == 0) || - ((long) ((int *)buffer) & 0x3) || - (offset & 0x3) || - (size & 0x3)) { - ERROR("Invalid read parameter"); - return -1; - } - - if (CAD_QSPI_INDRD_RD_STAT(mmio_read_32(CAD_QSPI_OFFSET + - CAD_QSPI_INDRD))) { - ERROR("Read in progress"); - return -1; - } - - /* - * bank_count : Number of bank(s) affected, including partial banks. - * bank_addr : Aligned address of the first bank, - * including partial bank. - * bank_ofst : The offset of the bank to read. - * Only used when reading the first bank. - */ - bank_count = CAD_QSPI_BANK_ADDR(offset + size - 1) - - CAD_QSPI_BANK_ADDR(offset) + 1; - bank_addr = offset & CAD_QSPI_BANK_ADDR_MSK; - bank_offset = offset & (CAD_QSPI_BANK_SIZE - 1); - - read_data = (uint8_t *)buffer; - - copy_len = LESS(size, CAD_QSPI_BANK_SIZE - bank_offset); - - for (i = 0; i < bank_count; ++i) { - status = cad_qspi_device_bank_select(CAD_QSPI_BANK_ADDR( - bank_addr)); - if (status != 0) - break; - status = cad_qspi_read_bank(read_data, bank_offset, copy_len); - if (status != 0) - break; - - bank_addr += CAD_QSPI_BANK_SIZE; - read_data += copy_len; - size -= copy_len; - bank_offset = 0; - copy_len = LESS(size, CAD_QSPI_BANK_SIZE); - } - - return status; -} - -int cad_qspi_erase(uint32_t offset, uint32_t size) -{ - int status = 0; - uint32_t subsector_offset = offset & (CAD_QSPI_SUBSECTOR_SIZE - 1); - uint32_t erase_size = LESS(size, - CAD_QSPI_SUBSECTOR_SIZE - subsector_offset); - - while (size) { - status = cad_qspi_erase_subsector(offset); - if (status != 0) - break; - - offset += erase_size; - size -= erase_size; - erase_size = LESS(size, CAD_QSPI_SUBSECTOR_SIZE); - } - return status; -} - -int cad_qspi_write(void *buffer, uint32_t offset, uint32_t size) -{ - int status, i; - uint32_t bank_count, bank_addr, bank_offset, copy_len; - uint8_t *write_data; - - status = 0; - - if ((offset >= qspi_device_size) || - (offset + size - 1 >= qspi_device_size) || - (size == 0) || - ((long)buffer & 0x3) || - (offset & 0x3) || - (size & 0x3)) - return -2; - - if (CAD_QSPI_INDWR_RDSTAT(mmio_read_32(CAD_QSPI_OFFSET + - CAD_QSPI_INDWR))) { - ERROR("QSPI Error: Write in progress\n"); - return -1; - } - - bank_count = CAD_QSPI_BANK_ADDR(offset + size - 1) - - CAD_QSPI_BANK_ADDR(offset) + 1; - bank_addr = offset & CAD_QSPI_BANK_ADDR_MSK; - bank_offset = offset & (CAD_QSPI_BANK_SIZE - 1); - - write_data = buffer; - - copy_len = LESS(size, CAD_QSPI_BANK_SIZE - bank_offset); - - for (i = 0; i < bank_count; ++i) { - status = cad_qspi_device_bank_select( - CAD_QSPI_BANK_ADDR(bank_addr)); - if (status != 0) - break; - - status = cad_qspi_write_bank(bank_offset, write_data, - copy_len); - if (status != 0) - break; - - bank_addr += CAD_QSPI_BANK_SIZE; - write_data += copy_len; - size -= copy_len; - bank_offset = 0; - - copy_len = LESS(size, CAD_QSPI_BANK_SIZE); - } - return status; -} - -int cad_qspi_update(void *Buffer, uint32_t offset, uint32_t size) -{ - int status = 0; - - status = cad_qspi_erase(offset, size); - if (status != 0) - return status; - - return cad_qspi_write(Buffer, offset, size); -} - -void cad_qspi_reset(void) -{ - cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_RESET_EN, 0); - cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_RESET_MEM, 0); -} - diff --git a/plat/intel/soc/stratix10/drivers/qspi/cadence_qspi.h b/plat/intel/soc/stratix10/drivers/qspi/cadence_qspi.h deleted file mode 100644 index e419161..0000000 --- a/plat/intel/soc/stratix10/drivers/qspi/cadence_qspi.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef __CAD_QSPI_H__ -#define __CAD_QSPI_H__ - -#define CAD_QSPI_MICRON_N25Q_SUPPORT 1 - -#define CAD_QSPI_OFFSET 0xff8d2000 - -#define CAD_INVALID -1 -#define CAD_QSPI_ERROR -2 - -#define CAD_QSPI_ADDR_FASTREAD 0 -#define CAD_QSPI_ADDR_FASTREAD_DUAL_IO 1 -#define CAD_QSPI_ADDR_FASTREAD_QUAD_IO 2 -#define CAT_QSPI_ADDR_SINGLE_IO 0 -#define CAT_QSPI_ADDR_DUAL_IO 1 -#define CAT_QSPI_ADDR_QUAD_IO 2 - -#define CAD_QSPI_BANK_ADDR(x) ((x) >> 24) -#define CAD_QSPI_BANK_ADDR_MSK 0xff000000 - -#define CAD_QSPI_COMMAND_TIMEOUT 0x10000000 - -#define CAD_QSPI_CFG 0x0 -#define CAD_QSPI_CFG_BAUDDIV_MSK 0xff87ffff -#define CAD_QSPI_CFG_BAUDDIV(x) (((x) << 19) & 0x780000) -#define CAD_QSPI_CFG_CS_MSK ~0x3c00 -#define CAD_QSPI_CFG_CS(x) (((x) << 11)) -#define CAD_QSPI_CFG_ENABLE (1 << 0) -#define CAD_QSPI_CFG_ENDMA_CLR_MSK 0xffff7fff -#define CAD_QSPI_CFG_IDLE (1 << 31) -#define CAD_QSPI_CFG_SELCLKPHASE_CLR_MSK 0xfffffffb -#define CAD_QSPI_CFG_SELCLKPOL_CLR_MSK 0xfffffffd - -#define CAD_QSPIDATA_OFST 0xff900000 - -#define CAD_QSPI_DELAY 0xc -#define CAD_QSPI_DELAY_CSSOT(x) (((x) & 0xff) << 0) -#define CAD_QSPI_DELAY_CSEOT(x) (((x) & 0xff) << 8) -#define CAD_QSPI_DELAY_CSDADS(x) (((x) & 0xff) << 16) -#define CAD_QSPI_DELAY_CSDA(x) (((x) & 0xff) << 24) - -#define CAD_QSPI_DEVSZ 0x14 -#define CAD_QSPI_DEVSZ_ADDR_BYTES(x) ((x) << 0) -#define CAD_QSPI_DEVSZ_BYTES_PER_PAGE(x) ((x) << 4) -#define CAD_QSPI_DEVSZ_BYTES_PER_BLOCK(x) ((x) << 16) - -#define CAD_QSPI_DEVWR 0x8 -#define CAD_QSPI_DEVRD 0x4 -#define CAD_QSPI_DEV_OPCODE(x) (((x) & 0xff) << 0) -#define CAD_QSPI_DEV_INST_TYPE(x) (((x) & 0x03) << 8) -#define CAD_QSPI_DEV_ADDR_TYPE(x) (((x) & 0x03) << 12) -#define CAD_QSPI_DEV_DATA_TYPE(x) (((x) & 0x03) << 16) -#define CAD_QSPI_DEV_MODE_BIT(x) (((x) & 0x01) << 20) -#define CAD_QSPI_DEV_DUMMY_CLK_CYCLE(x) (((x) & 0x0f) << 24) - -#define CAD_QSPI_FLASHCMD 0x90 -#define CAD_QSPI_FLASHCMD_ADDR 0x94 -#define CAD_QSPI_FLASHCMD_EXECUTE 0x1 -#define CAD_QSPI_FLASHCMD_EXECUTE_STAT 0x2 -#define CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX 5 -#define CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES(x) (((x) << 7) & 0x000f80) -#define CAD_QSPI_FLASHCMD_OPCODE(x) (((x) & 0xff) << 24) -#define CAD_QSPI_FLASHCMD_ENRDDATA(x) (((x) & 1) << 23) -#define CAD_QSPI_FLASHCMD_NUMRDDATABYTES(x) (((x) & 0xf) << 20) -#define CAD_QSPI_FLASHCMD_ENCMDADDR(x) (((x) & 1) << 19) -#define CAD_QSPI_FLASHCMD_ENMODEBIT(x) (((x) & 1) << 18) -#define CAD_QSPI_FLASHCMD_NUMADDRBYTES(x) (((x) & 0x3) << 16) -#define CAD_QSPI_FLASHCMD_ENWRDATA(x) (((x) & 1) << 15) -#define CAD_QSPI_FLASHCMD_NUMWRDATABYTES(x) (((x) & 0x7) << 12) -#define CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(x) (((x) & 0x1f) << 7) -#define CAD_QSPI_FLASHCMD_RDDATA0 0xa0 -#define CAD_QSPI_FLASHCMD_RDDATA1 0xa4 -#define CAD_QSPI_FLASHCMD_WRDATA0 0xa8 -#define CAD_QSPI_FLASHCMD_WRDATA1 0xac - -#define CAD_QSPI_RDDATACAP 0x10 -#define CAD_QSPI_RDDATACAP_BYP(x) (((x) & 1) << 0) -#define CAD_QSPI_RDDATACAP_DELAY(x) (((x) & 0xf) << 1) - -#define CAD_QSPI_REMAPADDR 0x24 -#define CAD_QSPI_REMAPADDR_VALUE_SET(x) (((x) & 0xffffffff) << 0) - -#define CAD_QSPI_SRAMPART 0x18 -#define CAD_QSPI_SRAMFILL 0x2c -#define CAD_QSPI_SRAMPART_ADDR(x) (((x) >> 0) & 0x3ff) -#define CAD_QSPI_SRAM_FIFO_ENTRY_COUNT (512 / sizeof(uint32_t)) -#define CAD_QSPI_SRAMFILL_INDWRPART(x) (((x) >> 16) & 0x00ffff) -#define CAD_QSPI_SRAMFILL_INDRDPART(x) (((x) >> 0) & 0x00ffff) - -#define CAD_QSPI_SELCLKPHASE(x) (((x) & 1) << 2) -#define CAD_QSPI_SELCLKPOL(x) (((x) & 1) << 1) - -#define CAD_QSPI_STIG_FLAGSR_PROGRAMREADY(x) (((x) >> 7) & 1) -#define CAD_QSPI_STIG_FLAGSR_ERASEREADY(x) (((x) >> 7) & 1) -#define CAD_QSPI_STIG_FLAGSR_ERASEERROR(x) (((x) >> 5) & 1) -#define CAD_QSPI_STIG_FLAGSR_PROGRAMERROR(x) (((x) >> 4) & 1) -#define CAD_QSPI_STIG_OPCODE_CLFSR 0x50 -#define CAD_QSPI_STIG_OPCODE_RDID 0x9f -#define CAD_QSPI_STIG_OPCODE_WRDIS 0x4 -#define CAD_QSPI_STIG_OPCODE_WREN 0x6 -#define CAD_QSPI_STIG_OPCODE_SUBSEC_ERASE 0x20 -#define CAD_QSPI_STIG_OPCODE_SEC_ERASE 0xd8 -#define CAD_QSPI_STIG_OPCODE_WREN_EXT_REG 0xc5 -#define CAD_QSPI_STIG_OPCODE_DIE_ERASE 0xc4 -#define CAD_QSPI_STIG_OPCODE_BULK_ERASE 0xc7 -#define CAD_QSPI_STIG_OPCODE_RDSR 0x5 -#define CAD_QSPI_STIG_OPCODE_RDFLGSR 0x70 -#define CAD_QSPI_STIG_OPCODE_RESET_EN 0x66 -#define CAD_QSPI_STIG_OPCODE_RESET_MEM 0x99 -#define CAD_QSPI_STIG_RDID_CAPACITYID(x) (((x) >> 16) & 0xff) -#define CAD_QSPI_STIG_SR_BUSY(x) (((x) >> 0) & 1) - - -#define CAD_QSPI_INST_SINGLE 0 -#define CAD_QSPI_INST_DUAL 1 -#define CAD_QSPI_INST_QUAD 2 - -#define CAD_QSPI_INDRDSTADDR 0x68 -#define CAD_QSPI_INDRDCNT 0x6c -#define CAD_QSPI_INDRD 0x60 -#define CAD_QSPI_INDRD_RD_STAT(x) (((x) >> 2) & 1) -#define CAD_QSPI_INDRD_START 1 -#define CAD_QSPI_INDRD_IND_OPS_DONE 0x20 - -#define CAD_QSPI_INDWR 0x70 -#define CAD_QSPI_INDWR_RDSTAT(x) (((x) >> 2) & 1) -#define CAD_QSPI_INDWRSTADDR 0x78 -#define CAD_QSPI_INDWRCNT 0x7c -#define CAD_QSPI_INDWR 0x70 -#define CAD_QSPI_INDWR_START 0x1 -#define CAD_QSPI_INDWR_INDDONE 0x20 - -#define CAD_QSPI_INT_STATUS_ALL 0x0000ffff - -#define CAD_QSPI_N25Q_DIE_SIZE 0x02000000 -#define CAD_QSPI_BANK_SIZE 0x01000000 -#define CAD_QSPI_PAGE_SIZE 0x00000100 - -#define CAD_QSPI_IRQMSK 0x44 - -#define CAD_QSPI_SUBSECTOR_SIZE 0x1000 - -#define S10_QSPI_ADDR_BYTES 2 -#define S10_QSPI_BYTES_PER_DEV 256 -#define S10_BYTES_PER_BLOCK 16 - -#define QSPI_FAST_READ 0xb - -// QSPI CONFIGURATIONS - -#define QSPI_CONFIG_CPOL 1 -#define QSPI_CONFIG_CPHA 1 - -#define QSPI_CONFIG_CSSOT 0x14 -#define QSPI_CONFIG_CSEOT 0x14 -#define QSPI_CONFIG_CSDADS 0xff -#define QSPI_CONFIG_CSDA 0xc8 - -int cad_qspi_init(uint32_t desired_clk_freq, uint32_t clk_phase, - uint32_t clk_pol, uint32_t csda, uint32_t csdads, - uint32_t cseot, uint32_t cssot, uint32_t rddatacap); -void cad_qspi_set_chip_select(int cs); -int cad_qspi_erase(uint32_t offset, uint32_t size); -int cad_qspi_write(void *buffer, uint32_t offset, uint32_t size); -int cad_qspi_read(void *buffer, uint32_t offset, uint32_t size); -int cad_qspi_update(void *buffer, uint32_t offset, uint32_t size); - -#endif - diff --git a/plat/intel/soc/stratix10/drivers/wdt/watchdog.c b/plat/intel/soc/stratix10/drivers/wdt/watchdog.c deleted file mode 100644 index b4dbe5f..0000000 --- a/plat/intel/soc/stratix10/drivers/wdt/watchdog.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019, Intel Corporation. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include -#include - -#include "watchdog.h" - - -/* Reset watchdog timer */ -void watchdog_sw_rst(void) -{ - mmio_write_32(WDT_CRR, WDT_SW_RST); -} - -/* Print component information */ -void watchdog_info(void) -{ - INFO("Component Type : %x\r\n", mmio_read_32(WDT_COMP_VERSION)); - INFO("Component Version : %x\r\n", mmio_read_32(WDT_COMP_TYPE)); -} - -/* Check watchdog current status */ -void watchdog_status(void) -{ - if (mmio_read_32(WDT_CR) & 1) { - INFO("Watchdog Timer in currently enabled\n"); - INFO("Current Counter : 0x%x\r\n", mmio_read_32(WDT_CCVR)); - } else { - INFO("Watchdog Timer in currently disabled\n"); - } -} - -/* Initialize & enable watchdog */ -void watchdog_init(int watchdog_clk) -{ - uint8_t cycles_i = 0; - uint32_t wdt_cycles = WDT_MIN_CYCLES; - uint32_t top_init_cycles = WDT_PERIOD * watchdog_clk; - - while ((cycles_i < 15) && (wdt_cycles < top_init_cycles)) { - wdt_cycles = (wdt_cycles << 1); - cycles_i++; - } - - mmio_write_32(WDT_TORR, (cycles_i << 4) | cycles_i); - - watchdog_enable(); -} - -void watchdog_enable(void) -{ - mmio_write_32(WDT_CR, WDT_CR_RMOD|WDT_CR_EN); -} diff --git a/plat/intel/soc/stratix10/drivers/wdt/watchdog.h b/plat/intel/soc/stratix10/drivers/wdt/watchdog.h deleted file mode 100644 index e920236..0000000 --- a/plat/intel/soc/stratix10/drivers/wdt/watchdog.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2019, Intel Corporation. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef __CAD_WATCHDOG_H__ -#define __CAD_WATCHDOG_H__ - -#define WDT_BASE (0xFFD00200) -#define WDT_REG_SIZE_OFFSET (0x4) -#define WDT_MIN_CYCLES (65536) -#define WDT_PERIOD (20) - -#define WDT_CR (WDT_BASE + 0x0) -#define WDT_TORR (WDT_BASE + 0x4) - -#define WDT_CRR (WDT_BASE + 0xC) - -#define WDT_CCVR (WDT_BASE + 0x8) -#define WDT_STAT (WDT_BASE + 0x10) -#define WDT_EOI (WDT_BASE + 0x14) - -#define WDT_COMP_PARAM_1 (WDT_BASE + 0xF4) -#define WDT_COMP_VERSION (WDT_BASE + 0xF8) -#define WDT_COMP_TYPE (WDT_BASE + 0XFC) - -#define WDT_CR_RMOD (0x0) -#define WDT_CR_EN (0x1) - -#define WDT_SW_RST (0x76) - - -void watchdog_init(int watchdog_clk); -void watchdog_enable(void); -void watchdog_info(void); -void watchdog_status(void); -void watchdog_sw_rst(void); - -#endif diff --git a/plat/intel/soc/stratix10/platform.mk b/plat/intel/soc/stratix10/platform.mk index fdd6e45..c1d62da 100644 --- a/plat/intel/soc/stratix10/platform.mk +++ b/plat/intel/soc/stratix10/platform.mk @@ -7,6 +7,7 @@ PLAT_INCLUDES := \ -Iplat/intel/soc/stratix10/ \ -Iplat/intel/soc/stratix10/include/ \ + -Iplat/intel/soc/common/drivers/ PLAT_BL_COMMON_SOURCES := \ lib/xlat_tables/xlat_tables_common.c \ @@ -46,8 +47,8 @@ plat/intel/soc/stratix10/soc/s10_system_manager.c \ common/desc_image_load.c \ plat/intel/soc/stratix10/soc/s10_mailbox.c \ - plat/intel/soc/stratix10/drivers/qspi/cadence_qspi.c \ - plat/intel/soc/stratix10/drivers/wdt/watchdog.c + plat/intel/soc/common/drivers/qspi/cadence_qspi.c \ + plat/intel/soc/common/drivers/wdt/watchdog.c BL31_SOURCES += drivers/arm/cci/cci.c \ lib/cpus/aarch64/cortex_a53.S \