1b525a8f0SKuldeep Singh // SPDX-License-Identifier: BSD-3-Clause 2b525a8f0SKuldeep Singh /* 3b525a8f0SKuldeep Singh * NXP FlexSpi Controller Driver. 4b525a8f0SKuldeep Singh * Copyright 2021 NXP 5b525a8f0SKuldeep Singh * 6b525a8f0SKuldeep Singh */ 7b525a8f0SKuldeep Singh #include <endian.h> 8b525a8f0SKuldeep Singh #include <stdint.h> 9b525a8f0SKuldeep Singh #include <stdio.h> 10b525a8f0SKuldeep Singh #include <string.h> 11b525a8f0SKuldeep Singh 12b525a8f0SKuldeep Singh #include <common/debug.h> 13b525a8f0SKuldeep Singh #include <flash_info.h> 14b525a8f0SKuldeep Singh #include "fspi.h" 15b525a8f0SKuldeep Singh #include <fspi_api.h> 16b525a8f0SKuldeep Singh #include <xspi_error_codes.h> 17b525a8f0SKuldeep Singh 18b525a8f0SKuldeep Singh #ifdef DEBUG_FLEXSPI 19b525a8f0SKuldeep Singh #define PR printf("In [%s][%d]\n", __func__, __LINE__) 20b525a8f0SKuldeep Singh #define PRA(a, b) printf("In [%s][%d] %s="a"\n", __func__, __LINE__, #b, b) 21b525a8f0SKuldeep Singh #else 22b525a8f0SKuldeep Singh #define PR 23b525a8f0SKuldeep Singh #define PRA(a, b) 24b525a8f0SKuldeep Singh #endif 25b525a8f0SKuldeep Singh 26b525a8f0SKuldeep Singh /* 27b525a8f0SKuldeep Singh * This errata is valid for all NXP SoC. 28b525a8f0SKuldeep Singh */ 29b525a8f0SKuldeep Singh #define ERRATA_FLASH_A050272 1 30b525a8f0SKuldeep Singh 31b525a8f0SKuldeep Singh static uintptr_t fspi_base_reg_addr; 32b525a8f0SKuldeep Singh static uintptr_t fspi_flash_base_addr; 33b525a8f0SKuldeep Singh 34b525a8f0SKuldeep Singh static void fspi_RDSR(uint32_t *, const void *, uint32_t); 35b525a8f0SKuldeep Singh 36b525a8f0SKuldeep Singh static void fspi_writel(uint32_t x_addr, uint32_t x_val) 37b525a8f0SKuldeep Singh { 38b525a8f0SKuldeep Singh fspi_out32((uint32_t *)(fspi_base_reg_addr + x_addr), 39b525a8f0SKuldeep Singh (uint32_t) x_val); 40b525a8f0SKuldeep Singh } 41b525a8f0SKuldeep Singh 42b525a8f0SKuldeep Singh static uint32_t fspi_readl(uint32_t x_addr) 43b525a8f0SKuldeep Singh { 44b525a8f0SKuldeep Singh return fspi_in32((uint32_t *)(fspi_base_reg_addr + x_addr)); 45b525a8f0SKuldeep Singh } 46b525a8f0SKuldeep Singh 47b525a8f0SKuldeep Singh static void fspi_MDIS(uint8_t x_disable) 48b525a8f0SKuldeep Singh { 49b525a8f0SKuldeep Singh uint32_t ui_reg; 50b525a8f0SKuldeep Singh 51b525a8f0SKuldeep Singh ui_reg = fspi_readl(FSPI_MCR0); 52b525a8f0SKuldeep Singh if (x_disable != 0U) { 53b525a8f0SKuldeep Singh ui_reg |= FSPI_MCR0_MDIS; 54b525a8f0SKuldeep Singh } else { 55b525a8f0SKuldeep Singh ui_reg &= (uint32_t) (~FSPI_MCR0_MDIS); 56b525a8f0SKuldeep Singh } 57b525a8f0SKuldeep Singh 58b525a8f0SKuldeep Singh fspi_writel(FSPI_MCR0, ui_reg); 59b525a8f0SKuldeep Singh } 60b525a8f0SKuldeep Singh 61b525a8f0SKuldeep Singh static void fspi_lock_LUT(void) 62b525a8f0SKuldeep Singh { 63b525a8f0SKuldeep Singh fspi_writel(FSPI_LUTKEY, FSPI_LUTKEY_VALUE); 64b525a8f0SKuldeep Singh VERBOSE("%s 0x%x\n", __func__, fspi_readl(FSPI_LCKCR)); 65b525a8f0SKuldeep Singh fspi_writel(FSPI_LCKCR, FSPI_LCKER_LOCK); 66b525a8f0SKuldeep Singh VERBOSE("%s 0x%x\n", __func__, fspi_readl(FSPI_LCKCR)); 67b525a8f0SKuldeep Singh } 68b525a8f0SKuldeep Singh 69b525a8f0SKuldeep Singh static void fspi_unlock_LUT(void) 70b525a8f0SKuldeep Singh { 71b525a8f0SKuldeep Singh fspi_writel(FSPI_LUTKEY, FSPI_LUTKEY_VALUE); 72b525a8f0SKuldeep Singh VERBOSE("%s 0x%x\n", __func__, fspi_readl(FSPI_LCKCR)); 73b525a8f0SKuldeep Singh fspi_writel(FSPI_LCKCR, FSPI_LCKER_UNLOCK); 74b525a8f0SKuldeep Singh VERBOSE("%s 0x%x\n", __func__, fspi_readl(FSPI_LCKCR)); 75b525a8f0SKuldeep Singh } 76b525a8f0SKuldeep Singh 77b525a8f0SKuldeep Singh static void fspi_op_setup(uint32_t fspi_op_seq_id, bool ignore_flash_sz) 78b525a8f0SKuldeep Singh { 79b525a8f0SKuldeep Singh uint32_t x_addr, x_instr0 = 0, x_instr1 = 0, x_instr2 = 0; 80b525a8f0SKuldeep Singh uint32_t cmd_id1, cmd_id2; 81b525a8f0SKuldeep Singh 82b525a8f0SKuldeep Singh VERBOSE("In func %s\n", __func__); 83b525a8f0SKuldeep Singh 84b525a8f0SKuldeep Singh switch (fspi_op_seq_id) { 85b525a8f0SKuldeep Singh case FSPI_READ_SEQ_ID: 86b525a8f0SKuldeep Singh cmd_id1 = FSPI_NOR_CMD_READ; 87b525a8f0SKuldeep Singh cmd_id2 = FSPI_NOR_CMD_READ_4B; 88b525a8f0SKuldeep Singh x_instr2 = FSPI_INSTR_OPRND0(0) | FSPI_INSTR_PAD0(FSPI_LUT_PAD1) 89b525a8f0SKuldeep Singh | FSPI_INSTR_OPCODE0(FSPI_LUT_READ); 90b525a8f0SKuldeep Singh break; 91b525a8f0SKuldeep Singh case FSPI_FASTREAD_SEQ_ID: 92b525a8f0SKuldeep Singh cmd_id1 = FSPI_NOR_CMD_FASTREAD; 93b525a8f0SKuldeep Singh cmd_id2 = FSPI_NOR_CMD_FASTREAD_4B; 94b525a8f0SKuldeep Singh x_instr2 = FSPI_INSTR_OPRND0(8) | FSPI_INSTR_PAD0(FSPI_LUT_PAD1) 95b525a8f0SKuldeep Singh | FSPI_INSTR_OPCODE0(FSPI_DUMMY_SDR) 96b525a8f0SKuldeep Singh | FSPI_INSTR_OPRND1(0) 97b525a8f0SKuldeep Singh | FSPI_INSTR_PAD1(FSPI_LUT_PAD1) 98b525a8f0SKuldeep Singh | FSPI_INSTR_OPCODE1(FSPI_LUT_READ); 99b525a8f0SKuldeep Singh break; 100b525a8f0SKuldeep Singh case FSPI_WRITE_SEQ_ID: 101b525a8f0SKuldeep Singh cmd_id1 = FSPI_NOR_CMD_PP; 102b525a8f0SKuldeep Singh cmd_id2 = FSPI_NOR_CMD_PP_4B; 103b525a8f0SKuldeep Singh x_instr2 = FSPI_INSTR_OPRND0(0) | FSPI_INSTR_PAD0(FSPI_LUT_PAD1) 104b525a8f0SKuldeep Singh | FSPI_INSTR_OPCODE0(FSPI_LUT_WRITE); 105b525a8f0SKuldeep Singh break; 106b525a8f0SKuldeep Singh case FSPI_WREN_SEQ_ID: 107b525a8f0SKuldeep Singh cmd_id1 = FSPI_NOR_CMD_WREN; 108b525a8f0SKuldeep Singh cmd_id2 = FSPI_NOR_CMD_WREN; 109b525a8f0SKuldeep Singh break; 110b525a8f0SKuldeep Singh case FSPI_SE_SEQ_ID: 111b525a8f0SKuldeep Singh cmd_id1 = FSPI_NOR_CMD_SE_64K; 112b525a8f0SKuldeep Singh cmd_id2 = FSPI_NOR_CMD_SE_64K_4B; 113b525a8f0SKuldeep Singh break; 114b525a8f0SKuldeep Singh case FSPI_4K_SEQ_ID: 115b525a8f0SKuldeep Singh cmd_id1 = FSPI_NOR_CMD_SE_4K; 116b525a8f0SKuldeep Singh cmd_id2 = FSPI_NOR_CMD_SE_4K_4B; 117b525a8f0SKuldeep Singh break; 118b525a8f0SKuldeep Singh case FSPI_BE_SEQ_ID: 119b525a8f0SKuldeep Singh cmd_id1 = FSPI_NOR_CMD_BE; 120b525a8f0SKuldeep Singh cmd_id2 = FSPI_NOR_CMD_BE; 121b525a8f0SKuldeep Singh break; 122b525a8f0SKuldeep Singh case FSPI_RDSR_SEQ_ID: 123b525a8f0SKuldeep Singh cmd_id1 = FSPI_NOR_CMD_RDSR; 124b525a8f0SKuldeep Singh cmd_id2 = FSPI_NOR_CMD_RDSR; 125b525a8f0SKuldeep Singh break; 126*5199b3b9SJiafei Pan default: 127*5199b3b9SJiafei Pan ERROR("Unsupported command\n"); 128*5199b3b9SJiafei Pan return; 129b525a8f0SKuldeep Singh } 130b525a8f0SKuldeep Singh 131b525a8f0SKuldeep Singh x_addr = FSPI_LUTREG_OFFSET + (uint32_t)(0x10 * fspi_op_seq_id); 132b525a8f0SKuldeep Singh if ((F_FLASH_SIZE_BYTES <= SZ_16M_BYTES) || (ignore_flash_sz)) { 133b525a8f0SKuldeep Singh x_instr0 = FSPI_INSTR_OPRND0(cmd_id1); 134b525a8f0SKuldeep Singh x_instr1 = FSPI_INSTR_OPRND1(FSPI_LUT_ADDR24BIT); 135b525a8f0SKuldeep Singh VERBOSE("CMD_ID = %x offset = 0x%x\n", cmd_id1, x_addr); 136b525a8f0SKuldeep Singh } else { 137b525a8f0SKuldeep Singh x_instr0 = FSPI_INSTR_OPRND0(cmd_id2); 138b525a8f0SKuldeep Singh x_instr1 = FSPI_INSTR_OPRND1(FSPI_LUT_ADDR32BIT); 139b525a8f0SKuldeep Singh VERBOSE("CMD_ID = %x offset = 0x%x\n", cmd_id2, x_addr); 140b525a8f0SKuldeep Singh } 141b525a8f0SKuldeep Singh x_instr0 |= FSPI_INSTR_PAD0(FSPI_LUT_PAD1) 142b525a8f0SKuldeep Singh | FSPI_INSTR_OPCODE0(FSPI_LUT_CMD); 143b525a8f0SKuldeep Singh 144b525a8f0SKuldeep Singh x_instr1 |= FSPI_INSTR_PAD1(FSPI_LUT_PAD1) 145b525a8f0SKuldeep Singh | FSPI_INSTR_OPCODE1(FSPI_LUT_ADDR); 146b525a8f0SKuldeep Singh 147b525a8f0SKuldeep Singh if (fspi_op_seq_id == FSPI_RDSR_SEQ_ID) { 148b525a8f0SKuldeep Singh x_instr0 |= FSPI_INSTR_OPRND1(1) | FSPI_INSTR_PAD1(FSPI_LUT_PAD1) 149b525a8f0SKuldeep Singh | FSPI_INSTR_OPCODE1(FSPI_LUT_READ); 150b525a8f0SKuldeep Singh } else if ((fspi_op_seq_id != FSPI_BE_SEQ_ID) 151b525a8f0SKuldeep Singh && (fspi_op_seq_id != FSPI_WREN_SEQ_ID)) { 152b525a8f0SKuldeep Singh x_instr0 |= x_instr1; 153b525a8f0SKuldeep Singh } 154b525a8f0SKuldeep Singh 155b525a8f0SKuldeep Singh fspi_writel((x_addr), x_instr0); 156b525a8f0SKuldeep Singh fspi_writel((x_addr + U(0x4)), x_instr2); 157b525a8f0SKuldeep Singh fspi_writel((x_addr + U(0x8)), (uint32_t) 0x0); /* STOP command */ 158b525a8f0SKuldeep Singh fspi_writel((x_addr + U(0xc)), (uint32_t) 0x0); /* STOP command */ 159b525a8f0SKuldeep Singh } 160b525a8f0SKuldeep Singh 161b525a8f0SKuldeep Singh static void fspi_setup_LUT(void) 162b525a8f0SKuldeep Singh { 163b525a8f0SKuldeep Singh VERBOSE("In func %s\n", __func__); 164b525a8f0SKuldeep Singh fspi_unlock_LUT(); 165b525a8f0SKuldeep Singh 166b525a8f0SKuldeep Singh /* LUT Setup for READ Command 3-Byte low Frequency */ 167b525a8f0SKuldeep Singh fspi_op_setup(FSPI_READ_SEQ_ID, false); 168b525a8f0SKuldeep Singh 169b525a8f0SKuldeep Singh /* LUT Setup for FAST READ Command 3-Byte/4-Byte high Frequency */ 170b525a8f0SKuldeep Singh fspi_op_setup(FSPI_FASTREAD_SEQ_ID, false); 171b525a8f0SKuldeep Singh 172b525a8f0SKuldeep Singh /* LUT Setup for Page Program */ 173b525a8f0SKuldeep Singh fspi_op_setup(FSPI_WRITE_SEQ_ID, false); 174b525a8f0SKuldeep Singh 175b525a8f0SKuldeep Singh /* LUT Setup for WREN */ 176b525a8f0SKuldeep Singh fspi_op_setup(FSPI_WREN_SEQ_ID, true); 177b525a8f0SKuldeep Singh 178b525a8f0SKuldeep Singh /* LUT Setup for Sector_Erase */ 179b525a8f0SKuldeep Singh fspi_op_setup(FSPI_SE_SEQ_ID, false); 180b525a8f0SKuldeep Singh 181b525a8f0SKuldeep Singh /* LUT Setup for Sub Sector 4K Erase */ 182b525a8f0SKuldeep Singh fspi_op_setup(FSPI_4K_SEQ_ID, false); 183b525a8f0SKuldeep Singh 184b525a8f0SKuldeep Singh /* LUT Setup for Bulk_Erase */ 185b525a8f0SKuldeep Singh fspi_op_setup(FSPI_BE_SEQ_ID, true); 186b525a8f0SKuldeep Singh 187b525a8f0SKuldeep Singh /* Read Status */ 188b525a8f0SKuldeep Singh fspi_op_setup(FSPI_RDSR_SEQ_ID, true); 189b525a8f0SKuldeep Singh 190b525a8f0SKuldeep Singh fspi_lock_LUT(); 191b525a8f0SKuldeep Singh } 192b525a8f0SKuldeep Singh 193b525a8f0SKuldeep Singh static inline void fspi_ahb_invalidate(void) 194b525a8f0SKuldeep Singh { 195b525a8f0SKuldeep Singh uint32_t reg; 196b525a8f0SKuldeep Singh 197b525a8f0SKuldeep Singh VERBOSE("In func %s %d\n", __func__, __LINE__); 198b525a8f0SKuldeep Singh reg = fspi_readl(FSPI_MCR0); 199b525a8f0SKuldeep Singh reg |= FSPI_MCR0_SWRST; 200b525a8f0SKuldeep Singh fspi_writel(FSPI_MCR0, reg); 201b525a8f0SKuldeep Singh while ((fspi_readl(FSPI_MCR0) & FSPI_MCR0_SWRST) != 0) 202b525a8f0SKuldeep Singh ; /* FSPI_MCR0_SWRESET_MASK */ 203b525a8f0SKuldeep Singh VERBOSE("In func %s %d\n", __func__, __LINE__); 204b525a8f0SKuldeep Singh } 205b525a8f0SKuldeep Singh 206b525a8f0SKuldeep Singh #if defined(CONFIG_FSPI_AHB) 207b525a8f0SKuldeep Singh static void fspi_init_ahb(void) 208b525a8f0SKuldeep Singh { 209b525a8f0SKuldeep Singh uint32_t i, x_flash_cr2, seq_id; 210b525a8f0SKuldeep Singh 211b525a8f0SKuldeep Singh x_flash_cr2 = 0; 212b525a8f0SKuldeep Singh /* Reset AHB RX buffer CR configuration */ 213b525a8f0SKuldeep Singh for (i = 0; i < 8; i++) { 214b525a8f0SKuldeep Singh fspi_writel((FSPI_AHBRX_BUF0CR0 + 4 * i), 0U); 215b525a8f0SKuldeep Singh } 216b525a8f0SKuldeep Singh 217b525a8f0SKuldeep Singh /* Set ADATSZ with the maximum AHB buffer size */ 218b525a8f0SKuldeep Singh fspi_writel(FSPI_AHBRX_BUF7CR0, 219b525a8f0SKuldeep Singh ((uint32_t) ((FSPI_RX_MAX_AHBBUF_SIZE / 8U) | 220b525a8f0SKuldeep Singh FSPI_AHBRXBUF0CR7_PREF))); 221b525a8f0SKuldeep Singh 222b525a8f0SKuldeep Singh /* Known limitation handling: prefetch and 223b525a8f0SKuldeep Singh * no start address alignment.*/ 224b525a8f0SKuldeep Singh fspi_writel(FSPI_AHBCR, FSPI_AHBCR_PREF_EN); 225b525a8f0SKuldeep Singh INFO("xAhbcr=0x%x\n", fspi_readl(FSPI_AHBCR)); 226b525a8f0SKuldeep Singh 227b525a8f0SKuldeep Singh // Setup AHB READ sequenceID for all flashes. 228b525a8f0SKuldeep Singh x_flash_cr2 = fspi_readl(FSPI_FLSHA1CR2); 229b525a8f0SKuldeep Singh INFO("x_flash_cr2=0x%x\n", x_flash_cr2); 230b525a8f0SKuldeep Singh 231b525a8f0SKuldeep Singh seq_id = CONFIG_FSPI_FASTREAD ? 232b525a8f0SKuldeep Singh FSPI_FASTREAD_SEQ_ID : FSPI_READ_SEQ_ID; 233b525a8f0SKuldeep Singh x_flash_cr2 |= ((seq_id << FSPI_FLSHXCR2_ARDSEQI_SHIFT) & 0x1f); 234b525a8f0SKuldeep Singh 235b525a8f0SKuldeep Singh INFO("x_flash_cr2=0x%x\n", x_flash_cr2); 236b525a8f0SKuldeep Singh 237b525a8f0SKuldeep Singh fspi_writel(FSPI_FLSHA1CR2, x_flash_cr2); 238b525a8f0SKuldeep Singh x_flash_cr2 = fspi_readl(FSPI_FLSHA1CR2); 239b525a8f0SKuldeep Singh INFO("x_flash_cr2=0x%x\n", x_flash_cr2); 240b525a8f0SKuldeep Singh } 241b525a8f0SKuldeep Singh #endif 242b525a8f0SKuldeep Singh 243b525a8f0SKuldeep Singh int xspi_read(uint32_t pc_rx_addr, uint32_t *pc_rx_buf, uint32_t x_size_bytes) 244b525a8f0SKuldeep Singh { 245b525a8f0SKuldeep Singh if (x_size_bytes == 0) { 246b525a8f0SKuldeep Singh ERROR("Zero length reads are not allowed\n"); 247b525a8f0SKuldeep Singh return XSPI_READ_FAIL; 248b525a8f0SKuldeep Singh } 249b525a8f0SKuldeep Singh 250b525a8f0SKuldeep Singh #if defined(CONFIG_FSPI_AHB) 251b525a8f0SKuldeep Singh return xspi_ahb_read(pc_rx_addr, pc_rx_buf, x_size_bytes); 252b525a8f0SKuldeep Singh #else 253b525a8f0SKuldeep Singh return xspi_ip_read(pc_rx_addr, pc_rx_buf, x_size_bytes); 254b525a8f0SKuldeep Singh #endif 255b525a8f0SKuldeep Singh } 256b525a8f0SKuldeep Singh #if defined(CONFIG_FSPI_AHB) 257b525a8f0SKuldeep Singh int xspi_ahb_read(uint32_t pc_rx_addr, uint32_t *pc_rx_buf, uint32_t x_size_bytes) 258b525a8f0SKuldeep Singh { 259b525a8f0SKuldeep Singh VERBOSE("In func %s 0x%x\n", __func__, (pc_rx_addr)); 260b525a8f0SKuldeep Singh 261b525a8f0SKuldeep Singh if (F_FLASH_SIZE_BYTES <= SZ_16M_BYTES) { 262b525a8f0SKuldeep Singh pc_rx_addr = ((uint32_t)(pcRxAddr & MASK_24BIT_ADDRESS)); 263b525a8f0SKuldeep Singh } else { 264b525a8f0SKuldeep Singh pc_rx_addr = ((uint32_t)(pcRxAddr & MASK_32BIT_ADDRESS)); 265b525a8f0SKuldeep Singh } 266b525a8f0SKuldeep Singh 267b525a8f0SKuldeep Singh pc_rx_addr = ((uint32_t)(pcRxAddr + fspi_flash_base_addr)); 268b525a8f0SKuldeep Singh 269b525a8f0SKuldeep Singh if (((pc_rx_addr % 4) != 0) || (((uintptr_t)pc_rx_buf % 4) != 0)) { 270b525a8f0SKuldeep Singh WARN("%s: unaligned Start Address src=%ld dst=0x%p\n", 271b525a8f0SKuldeep Singh __func__, (pc_rx_addr - fspi_flash_base_addr), pc_rx_buf); 272b525a8f0SKuldeep Singh } 273b525a8f0SKuldeep Singh 274b525a8f0SKuldeep Singh /* Directly copy from AHB Buffer */ 275b525a8f0SKuldeep Singh memcpy(pc_rx_buf, (void *)(uintptr_t)pc_rx_addr, x_size_bytes); 276b525a8f0SKuldeep Singh 277b525a8f0SKuldeep Singh fspi_ahb_invalidate(); 278b525a8f0SKuldeep Singh return XSPI_SUCCESS; 279b525a8f0SKuldeep Singh } 280b525a8f0SKuldeep Singh #endif 281b525a8f0SKuldeep Singh 282b525a8f0SKuldeep Singh int xspi_ip_read(uint32_t pc_rx_addr, uint32_t *pv_rx_buf, uint32_t ui_len) 283b525a8f0SKuldeep Singh { 284b525a8f0SKuldeep Singh 285b525a8f0SKuldeep Singh uint32_t i = 0U, j = 0U, x_rem = 0U; 286b525a8f0SKuldeep Singh uint32_t x_iteration = 0U, x_size_rx = 0U, x_size_wm, temp_size; 287b525a8f0SKuldeep Singh uint32_t data = 0U; 288b525a8f0SKuldeep Singh uint32_t x_len_bytes; 289b525a8f0SKuldeep Singh uint32_t x_addr, sts0, intr, seq_id; 290b525a8f0SKuldeep Singh 291b525a8f0SKuldeep Singh x_addr = (uint32_t) pc_rx_addr; 292b525a8f0SKuldeep Singh x_len_bytes = ui_len; 293b525a8f0SKuldeep Singh 294b525a8f0SKuldeep Singh /* Watermark level : 8 bytes. (BY DEFAULT) */ 295b525a8f0SKuldeep Singh x_size_wm = 8U; 296b525a8f0SKuldeep Singh 297b525a8f0SKuldeep Singh /* Clear RX Watermark interrupt in INT register, if any existing. */ 298b525a8f0SKuldeep Singh fspi_writel(FSPI_INTR, FSPI_INTR_IPRXWA); 299b525a8f0SKuldeep Singh PRA("0x%x", fspi_readl(FSPI_INTR)); 300b525a8f0SKuldeep Singh /* Invalid the RXFIFO, to run next IP Command */ 301b525a8f0SKuldeep Singh /* Clears data entries in IP Rx FIFOs, Also reset R/W pointers */ 302b525a8f0SKuldeep Singh fspi_writel(FSPI_IPRXFCR, FSPI_IPRXFCR_CLR); 303b525a8f0SKuldeep Singh fspi_writel(FSPI_INTR, FSPI_INTEN_IPCMDDONE); 304b525a8f0SKuldeep Singh 305b525a8f0SKuldeep Singh while (x_len_bytes) { 306b525a8f0SKuldeep Singh 307b525a8f0SKuldeep Singh /* FlexSPI can store no more than FSPI_RX_IPBUF_SIZE */ 308b525a8f0SKuldeep Singh x_size_rx = (x_len_bytes > FSPI_RX_IPBUF_SIZE) ? 309b525a8f0SKuldeep Singh FSPI_RX_IPBUF_SIZE : x_len_bytes; 310b525a8f0SKuldeep Singh 311b525a8f0SKuldeep Singh /* IP Control Register0 - SF Address to be read */ 312b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCR0, x_addr); 313b525a8f0SKuldeep Singh PRA("0x%x", fspi_readl(FSPI_IPCR0)); 314b525a8f0SKuldeep Singh /* IP Control Register1 - SEQID_READ operation, Size */ 315b525a8f0SKuldeep Singh 316b525a8f0SKuldeep Singh seq_id = CONFIG_FSPI_FASTREAD ? 317b525a8f0SKuldeep Singh FSPI_FASTREAD_SEQ_ID : FSPI_READ_SEQ_ID; 318b525a8f0SKuldeep Singh 319b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCR1, 320b525a8f0SKuldeep Singh (uint32_t)(seq_id << FSPI_IPCR1_ISEQID_SHIFT) | 321b525a8f0SKuldeep Singh (uint16_t) x_size_rx); 322b525a8f0SKuldeep Singh 323b525a8f0SKuldeep Singh PRA("0x%x", fspi_readl(FSPI_IPCR1)); 324b525a8f0SKuldeep Singh 325b525a8f0SKuldeep Singh do { 326b525a8f0SKuldeep Singh sts0 = fspi_readl(FSPI_STS0); 327b525a8f0SKuldeep Singh } while (((sts0 & FSPI_STS0_ARB_IDLE) == 0) && 328b525a8f0SKuldeep Singh ((sts0 & FSPI_STS0_SEQ_IDLE) == 0)); 329b525a8f0SKuldeep Singh 330b525a8f0SKuldeep Singh /* Trigger IP Read Command */ 331b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); 332b525a8f0SKuldeep Singh PRA("0x%x", fspi_readl(FSPI_IPCMD)); 333b525a8f0SKuldeep Singh 334b525a8f0SKuldeep Singh intr = fspi_readl(FSPI_INTR); 335b525a8f0SKuldeep Singh if (((intr & FSPI_INTR_IPCMDGE) != 0) || 336b525a8f0SKuldeep Singh ((intr & FSPI_INTR_IPCMDERR) != 0)) { 337b525a8f0SKuldeep Singh ERROR("Error in IP READ INTR=0x%x\n", intr); 338b525a8f0SKuldeep Singh return -XSPI_IP_READ_FAIL; 339b525a8f0SKuldeep Singh } 340b525a8f0SKuldeep Singh /* Will read in n iterations of each 8 FIFO's(WM level) */ 341b525a8f0SKuldeep Singh x_iteration = x_size_rx / x_size_wm; 342b525a8f0SKuldeep Singh for (i = 0U; i < x_iteration; i++) { 343b525a8f0SKuldeep Singh if ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPRXWA_MASK) == 0) { 344b525a8f0SKuldeep Singh PRA("0x%x", fspi_readl(FSPI_INTR)); 345b525a8f0SKuldeep Singh } 346b525a8f0SKuldeep Singh /* Wait for IP Rx Watermark Fill event */ 347b525a8f0SKuldeep Singh while (!(fspi_readl(FSPI_INTR) & FSPI_INTR_IPRXWA_MASK)) { 348b525a8f0SKuldeep Singh PRA("0x%x", fspi_readl(FSPI_INTR)); 349b525a8f0SKuldeep Singh } 350b525a8f0SKuldeep Singh 351b525a8f0SKuldeep Singh /* Read RX FIFO's(upto WM level) & copy to rxbuffer */ 352b525a8f0SKuldeep Singh for (j = 0U; j < x_size_wm; j += 4U) { 353b525a8f0SKuldeep Singh /* Read FIFO Data Register */ 354b525a8f0SKuldeep Singh data = fspi_readl(FSPI_RFDR + j); 355b525a8f0SKuldeep Singh #if FSPI_IPDATA_SWAP /* Just In case you want swap */ 356b525a8f0SKuldeep Singh data = bswap32(data); 357b525a8f0SKuldeep Singh #endif 358b525a8f0SKuldeep Singh memcpy(pv_rx_buf++, &data, 4); 359b525a8f0SKuldeep Singh } 360b525a8f0SKuldeep Singh 361b525a8f0SKuldeep Singh /* Clear IP_RX_WATERMARK Event in INTR register */ 362b525a8f0SKuldeep Singh /* Reset FIFO Read pointer for next iteration.*/ 363b525a8f0SKuldeep Singh fspi_writel(FSPI_INTR, FSPI_INTR_IPRXWA); 364b525a8f0SKuldeep Singh } 365b525a8f0SKuldeep Singh 366b525a8f0SKuldeep Singh x_rem = x_size_rx % x_size_wm; 367b525a8f0SKuldeep Singh 368b525a8f0SKuldeep Singh if (x_rem != 0U) { 369b525a8f0SKuldeep Singh /* Wait for data filled */ 370b525a8f0SKuldeep Singh while (!(fspi_readl(FSPI_IPRXFSTS) & FSPI_IPRXFSTS_FILL_MASK)) { 371b525a8f0SKuldeep Singh PRA("0x%x", fspi_readl(FSPI_IPRXFSTS)); 372b525a8f0SKuldeep Singh } 373b525a8f0SKuldeep Singh 374b525a8f0SKuldeep Singh temp_size = 0; 375b525a8f0SKuldeep Singh j = 0U; 376b525a8f0SKuldeep Singh while (x_rem > 0U) { 377b525a8f0SKuldeep Singh data = 0U; 378b525a8f0SKuldeep Singh data = fspi_readl(FSPI_RFDR + j); 379b525a8f0SKuldeep Singh #if FSPI_IPDATA_SWAP /* Just In case you want swap */ 380b525a8f0SKuldeep Singh data = bswap32(data); 381b525a8f0SKuldeep Singh #endif 382b525a8f0SKuldeep Singh temp_size = (x_rem < 4) ? x_rem : 4; 383b525a8f0SKuldeep Singh memcpy(pv_rx_buf++, &data, temp_size); 384b525a8f0SKuldeep Singh x_rem -= temp_size; 385b525a8f0SKuldeep Singh } 386b525a8f0SKuldeep Singh } 387b525a8f0SKuldeep Singh 388b525a8f0SKuldeep Singh 389b525a8f0SKuldeep Singh while (!(fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK)) { 390b525a8f0SKuldeep Singh PRA("0x%x", fspi_readl(FSPI_INTR)); 391b525a8f0SKuldeep Singh } 392b525a8f0SKuldeep Singh 393b525a8f0SKuldeep Singh /* Invalid the RX FIFO, to run next IP Command */ 394b525a8f0SKuldeep Singh fspi_writel(FSPI_IPRXFCR, FSPI_IPRXFCR_CLR); 395b525a8f0SKuldeep Singh /* Clear IP Command Done flag in interrupt register*/ 396b525a8f0SKuldeep Singh fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); 397b525a8f0SKuldeep Singh 398b525a8f0SKuldeep Singh /* Update remaining len, Increment x_addr read pointer. */ 399b525a8f0SKuldeep Singh x_len_bytes -= x_size_rx; 400b525a8f0SKuldeep Singh x_addr += x_size_rx; 401b525a8f0SKuldeep Singh } 402b525a8f0SKuldeep Singh PR; 403b525a8f0SKuldeep Singh return XSPI_SUCCESS; 404b525a8f0SKuldeep Singh } 405b525a8f0SKuldeep Singh 406b525a8f0SKuldeep Singh void xspi_ip_write(uint32_t pc_wr_addr, uint32_t *pv_wr_buf, uint32_t ui_len) 407b525a8f0SKuldeep Singh { 408b525a8f0SKuldeep Singh 409b525a8f0SKuldeep Singh uint32_t x_iteration = 0U, x_rem = 0U; 410b525a8f0SKuldeep Singh uint32_t x_size_tx = 0U, x_size_wm, temp_size; 411b525a8f0SKuldeep Singh uint32_t i = 0U, j = 0U; 412b525a8f0SKuldeep Singh uint32_t ui_data = 0U; 413b525a8f0SKuldeep Singh uint32_t x_addr, x_len_bytes; 414b525a8f0SKuldeep Singh 415b525a8f0SKuldeep Singh 416b525a8f0SKuldeep Singh x_size_wm = 8U; /* Default TX WaterMark level: 8 Bytes. */ 417b525a8f0SKuldeep Singh x_addr = (uint32_t)pc_wr_addr; 418b525a8f0SKuldeep Singh x_len_bytes = ui_len; 419b525a8f0SKuldeep Singh VERBOSE("In func %s[%d] x_addr =0x%x xLen_bytes=%d\n", 420b525a8f0SKuldeep Singh __func__, __LINE__, x_addr, x_len_bytes); 421b525a8f0SKuldeep Singh 422b525a8f0SKuldeep Singh while (x_len_bytes != 0U) { 423b525a8f0SKuldeep Singh 424b525a8f0SKuldeep Singh x_size_tx = (x_len_bytes > FSPI_TX_IPBUF_SIZE) ? 425b525a8f0SKuldeep Singh FSPI_TX_IPBUF_SIZE : x_len_bytes; 426b525a8f0SKuldeep Singh 427b525a8f0SKuldeep Singh /* IP Control Register0 - SF Address to be read */ 428b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCR0, x_addr); 429b525a8f0SKuldeep Singh INFO("In func %s[%d] x_addr =0x%x xLen_bytes=%d\n", 430b525a8f0SKuldeep Singh __func__, __LINE__, x_addr, x_len_bytes); 431b525a8f0SKuldeep Singh 432b525a8f0SKuldeep Singh /* 433b525a8f0SKuldeep Singh * Fill TX FIFO's.. 434b525a8f0SKuldeep Singh * 435b525a8f0SKuldeep Singh */ 436b525a8f0SKuldeep Singh 437b525a8f0SKuldeep Singh x_iteration = x_size_tx / x_size_wm; 438b525a8f0SKuldeep Singh for (i = 0U; i < x_iteration; i++) { 439b525a8f0SKuldeep Singh 440b525a8f0SKuldeep Singh /* Ensure TX FIFO Watermark Available */ 441b525a8f0SKuldeep Singh while ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPTXWE_MASK) == 0) 442b525a8f0SKuldeep Singh ; 443b525a8f0SKuldeep Singh 444b525a8f0SKuldeep Singh 445b525a8f0SKuldeep Singh /* Fill TxFIFO's ( upto watermark level) */ 446b525a8f0SKuldeep Singh for (j = 0U; j < x_size_wm; j += 4U) { 447b525a8f0SKuldeep Singh memcpy(&ui_data, pv_wr_buf++, 4); 448b525a8f0SKuldeep Singh /* Write TX FIFO Data Register */ 449b525a8f0SKuldeep Singh fspi_writel((FSPI_TFDR + j), ui_data); 450b525a8f0SKuldeep Singh 451b525a8f0SKuldeep Singh } 452b525a8f0SKuldeep Singh 453b525a8f0SKuldeep Singh /* Clear IP_TX_WATERMARK Event in INTR register */ 454b525a8f0SKuldeep Singh /* Reset the FIFO Write pointer for next iteration */ 455b525a8f0SKuldeep Singh fspi_writel(FSPI_INTR, FSPI_INTR_IPTXWE); 456b525a8f0SKuldeep Singh } 457b525a8f0SKuldeep Singh 458b525a8f0SKuldeep Singh x_rem = x_size_tx % x_size_wm; 459b525a8f0SKuldeep Singh 460b525a8f0SKuldeep Singh if (x_rem != 0U) { 461b525a8f0SKuldeep Singh /* Wait for TXFIFO empty */ 462b525a8f0SKuldeep Singh while (!(fspi_readl(FSPI_INTR) & FSPI_INTR_IPTXWE)) 463b525a8f0SKuldeep Singh ; 464b525a8f0SKuldeep Singh 465b525a8f0SKuldeep Singh temp_size = 0U; 466b525a8f0SKuldeep Singh j = 0U; 467b525a8f0SKuldeep Singh while (x_rem > 0U) { 468b525a8f0SKuldeep Singh ui_data = 0U; 469b525a8f0SKuldeep Singh temp_size = (x_rem < 4U) ? x_rem : 4U; 470b525a8f0SKuldeep Singh memcpy(&ui_data, pv_wr_buf++, temp_size); 471b525a8f0SKuldeep Singh INFO("%d ---> pv_wr_buf=0x%p\n", __LINE__, pv_wr_buf); 472b525a8f0SKuldeep Singh fspi_writel((FSPI_TFDR + j), ui_data); 473b525a8f0SKuldeep Singh x_rem -= temp_size; 474b525a8f0SKuldeep Singh j += 4U ; /* TODO: May not be needed*/ 475b525a8f0SKuldeep Singh } 476b525a8f0SKuldeep Singh /* Clear IP_TX_WATERMARK Event in INTR register */ 477b525a8f0SKuldeep Singh /* Reset FIFO's Write pointer for next iteration.*/ 478b525a8f0SKuldeep Singh fspi_writel(FSPI_INTR, FSPI_INTR_IPTXWE); 479b525a8f0SKuldeep Singh } 480b525a8f0SKuldeep Singh 481b525a8f0SKuldeep Singh /* IP Control Register1 - SEQID_WRITE operation, Size */ 482b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCR1, (uint32_t)(FSPI_WRITE_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | (uint16_t) x_size_tx); 483b525a8f0SKuldeep Singh /* Trigger IP Write Command */ 484b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); 485b525a8f0SKuldeep Singh 486b525a8f0SKuldeep Singh /* Wait for IP Write command done */ 487b525a8f0SKuldeep Singh while (!(fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK)) 488b525a8f0SKuldeep Singh ; 489b525a8f0SKuldeep Singh 490b525a8f0SKuldeep Singh /* Invalidate TX FIFOs & acknowledge IP_CMD_DONE event */ 491b525a8f0SKuldeep Singh fspi_writel(FSPI_IPTXFCR, FSPI_IPTXFCR_CLR); 492b525a8f0SKuldeep Singh fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); 493b525a8f0SKuldeep Singh 494b525a8f0SKuldeep Singh /* for next iteration */ 495b525a8f0SKuldeep Singh x_len_bytes -= x_size_tx; 496b525a8f0SKuldeep Singh x_addr += x_size_tx; 497b525a8f0SKuldeep Singh } 498b525a8f0SKuldeep Singh 499b525a8f0SKuldeep Singh } 500b525a8f0SKuldeep Singh 501b525a8f0SKuldeep Singh int xspi_write(uint32_t pc_wr_addr, void *pv_wr_buf, uint32_t ui_len) 502b525a8f0SKuldeep Singh { 503b525a8f0SKuldeep Singh 504b525a8f0SKuldeep Singh uint32_t x_addr; 505b525a8f0SKuldeep Singh uint32_t x_page1_len = 0U, x_page_l_len = 0U; 506b525a8f0SKuldeep Singh uint32_t i, j = 0U; 507b525a8f0SKuldeep Singh void *buf = pv_wr_buf; 508b525a8f0SKuldeep Singh 509b525a8f0SKuldeep Singh VERBOSE("\nIn func %s\n", __func__); 510b525a8f0SKuldeep Singh 511b525a8f0SKuldeep Singh x_addr = (uint32_t)(pc_wr_addr); 512b525a8f0SKuldeep Singh if ((ui_len <= F_PAGE_256) && ((x_addr % F_PAGE_256) == 0)) { 513b525a8f0SKuldeep Singh x_page1_len = ui_len; 514b525a8f0SKuldeep Singh INFO("%d ---> x_page1_len=0x%x x_page_l_len =0x%x j=0x%x\n", __LINE__, x_page1_len, x_page_l_len, j); 515b525a8f0SKuldeep Singh } else if ((ui_len <= F_PAGE_256) && ((x_addr % F_PAGE_256) != 0)) { 516b525a8f0SKuldeep Singh x_page1_len = (F_PAGE_256 - (x_addr % F_PAGE_256)); 517b525a8f0SKuldeep Singh if (ui_len > x_page1_len) { 518b525a8f0SKuldeep Singh x_page_l_len = (ui_len - x_page1_len) % F_PAGE_256; 519b525a8f0SKuldeep Singh } else { 520b525a8f0SKuldeep Singh x_page1_len = ui_len; 521b525a8f0SKuldeep Singh x_page_l_len = 0; 522b525a8f0SKuldeep Singh } 523b525a8f0SKuldeep Singh j = 0U; 524b525a8f0SKuldeep Singh INFO("%d 0x%x 0x%x\n", x_addr % F_PAGE_256, x_addr % F_PAGE_256, F_PAGE_256); 525b525a8f0SKuldeep Singh INFO("%d ---> x_page1_len=0x%x x_page_l_len =0x%x j=0x%x\n", __LINE__, x_page1_len, x_page_l_len, j); 526b525a8f0SKuldeep Singh } else if ((ui_len > F_PAGE_256) && ((x_addr % F_PAGE_256) == 0)) { 527b525a8f0SKuldeep Singh j = ui_len / F_PAGE_256; 528b525a8f0SKuldeep Singh x_page_l_len = ui_len % F_PAGE_256; 529b525a8f0SKuldeep Singh INFO("%d ---> x_page1_len=0x%x x_page_l_len =0x%x j=0x%x\n", __LINE__, x_page1_len, x_page_l_len, j); 530b525a8f0SKuldeep Singh } else if ((ui_len > F_PAGE_256) && ((x_addr % F_PAGE_256) != 0)) { 531b525a8f0SKuldeep Singh x_page1_len = (F_PAGE_256 - (x_addr % F_PAGE_256)); 532b525a8f0SKuldeep Singh j = (ui_len - x_page1_len) / F_PAGE_256; 533b525a8f0SKuldeep Singh x_page_l_len = (ui_len - x_page1_len) % F_PAGE_256; 534b525a8f0SKuldeep Singh INFO("%d ---> x_page1_len=0x%x x_page_l_len =0x%x j=0x%x\n", __LINE__, x_page1_len, x_page_l_len, j); 535b525a8f0SKuldeep Singh } 536b525a8f0SKuldeep Singh 537b525a8f0SKuldeep Singh if (x_page1_len != 0U) { 538b525a8f0SKuldeep Singh xspi_wren(x_addr); 539b525a8f0SKuldeep Singh xspi_ip_write(x_addr, (uint32_t *)buf, x_page1_len); 540b525a8f0SKuldeep Singh while (is_flash_busy()) 541b525a8f0SKuldeep Singh ; 542b525a8f0SKuldeep Singh INFO("%d Initial pc_wr_addr=0x%x, Final x_addr=0x%x, Initial ui_len=0x%x Final ui_len=0x%x\n", 543b525a8f0SKuldeep Singh __LINE__, pc_wr_addr, x_addr, ui_len, (x_addr-pc_wr_addr)); 544b525a8f0SKuldeep Singh INFO("Initial Buf pv_wr_buf=%p, final Buf=%p\n", pv_wr_buf, buf); 545b525a8f0SKuldeep Singh x_addr += x_page1_len; 546b525a8f0SKuldeep Singh /* TODO What is buf start is not 4 aligned */ 547b525a8f0SKuldeep Singh buf = buf + x_page1_len; 548b525a8f0SKuldeep Singh } 549b525a8f0SKuldeep Singh 550b525a8f0SKuldeep Singh for (i = 0U; i < j; i++) { 551b525a8f0SKuldeep Singh INFO("In for loop Buf pv_wr_buf=%p, final Buf=%p x_addr=0x%x offset_buf %d.\n", 552b525a8f0SKuldeep Singh pv_wr_buf, buf, x_addr, x_page1_len/4); 553b525a8f0SKuldeep Singh xspi_wren(x_addr); 554b525a8f0SKuldeep Singh xspi_ip_write(x_addr, (uint32_t *)buf, F_PAGE_256); 555b525a8f0SKuldeep Singh while (is_flash_busy()) 556b525a8f0SKuldeep Singh ; 557b525a8f0SKuldeep Singh INFO("%d Initial pc_wr_addr=0x%x, Final x_addr=0x%x, Initial ui_len=0x%x Final ui_len=0x%x\n", 558b525a8f0SKuldeep Singh __LINE__, pc_wr_addr, x_addr, ui_len, (x_addr-pc_wr_addr)); 559b525a8f0SKuldeep Singh x_addr += F_PAGE_256; 560b525a8f0SKuldeep Singh /* TODO What is buf start is not 4 aligned */ 561b525a8f0SKuldeep Singh buf = buf + F_PAGE_256; 562b525a8f0SKuldeep Singh INFO("Initial Buf pv_wr_buf=%p, final Buf=%p\n", pv_wr_buf, buf); 563b525a8f0SKuldeep Singh } 564b525a8f0SKuldeep Singh 565b525a8f0SKuldeep Singh if (x_page_l_len != 0U) { 566b525a8f0SKuldeep Singh INFO("%d Initial Buf pv_wr_buf=%p, final Buf=%p x_page_l_len=0x%x\n", __LINE__, pv_wr_buf, buf, x_page_l_len); 567b525a8f0SKuldeep Singh xspi_wren(x_addr); 568b525a8f0SKuldeep Singh xspi_ip_write(x_addr, (uint32_t *)buf, x_page_l_len); 569b525a8f0SKuldeep Singh while (is_flash_busy()) 570b525a8f0SKuldeep Singh ; 571b525a8f0SKuldeep Singh INFO("%d Initial pc_wr_addr=0x%x, Final x_addr=0x%x, Initial ui_len=0x%x Final ui_len=0x%x\n", 572b525a8f0SKuldeep Singh __LINE__, pc_wr_addr, x_addr, ui_len, (x_addr-pc_wr_addr)); 573b525a8f0SKuldeep Singh } 574b525a8f0SKuldeep Singh 575b525a8f0SKuldeep Singh VERBOSE("Now calling func call Invalidate%s\n", __func__); 576b525a8f0SKuldeep Singh fspi_ahb_invalidate(); 577b525a8f0SKuldeep Singh return XSPI_SUCCESS; 578b525a8f0SKuldeep Singh } 579b525a8f0SKuldeep Singh 580b525a8f0SKuldeep Singh int xspi_wren(uint32_t pc_wr_addr) 581b525a8f0SKuldeep Singh { 582b525a8f0SKuldeep Singh VERBOSE("In func %s Addr=0x%x\n", __func__, pc_wr_addr); 583b525a8f0SKuldeep Singh 584b525a8f0SKuldeep Singh fspi_writel(FSPI_IPTXFCR, FSPI_IPTXFCR_CLR); 585b525a8f0SKuldeep Singh 586b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCR0, (uint32_t)pc_wr_addr); 587b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCR1, ((FSPI_WREN_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | 0)); 588b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); 589b525a8f0SKuldeep Singh 590b525a8f0SKuldeep Singh while ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK) == 0) 591b525a8f0SKuldeep Singh ; 592b525a8f0SKuldeep Singh 593b525a8f0SKuldeep Singh fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); 594b525a8f0SKuldeep Singh return XSPI_SUCCESS; 595b525a8f0SKuldeep Singh } 596b525a8f0SKuldeep Singh 597b525a8f0SKuldeep Singh static void fspi_bbluk_er(void) 598b525a8f0SKuldeep Singh { 599b525a8f0SKuldeep Singh VERBOSE("In func %s\n", __func__); 600b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCR0, 0x0); 601b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCR1, ((FSPI_BE_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | 20)); 602b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); 603b525a8f0SKuldeep Singh 604b525a8f0SKuldeep Singh while ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK) == 0) 605b525a8f0SKuldeep Singh ; 606b525a8f0SKuldeep Singh fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); 607b525a8f0SKuldeep Singh 608b525a8f0SKuldeep Singh } 609b525a8f0SKuldeep Singh 610b525a8f0SKuldeep Singh static void fspi_RDSR(uint32_t *rxbuf, const void *p_addr, uint32_t size) 611b525a8f0SKuldeep Singh { 612b525a8f0SKuldeep Singh uint32_t iprxfcr = 0U; 613b525a8f0SKuldeep Singh uint32_t data = 0U; 614b525a8f0SKuldeep Singh 615b525a8f0SKuldeep Singh iprxfcr = fspi_readl(FSPI_IPRXFCR); 616b525a8f0SKuldeep Singh /* IP RX FIFO would be read by processor */ 617b525a8f0SKuldeep Singh iprxfcr = iprxfcr & (uint32_t)~FSPI_IPRXFCR_CLR; 618b525a8f0SKuldeep Singh /* Invalid data entries in IP RX FIFO */ 619b525a8f0SKuldeep Singh iprxfcr = iprxfcr | FSPI_IPRXFCR_CLR; 620b525a8f0SKuldeep Singh fspi_writel(FSPI_IPRXFCR, iprxfcr); 621b525a8f0SKuldeep Singh 622b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCR0, (uintptr_t) p_addr); 623b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCR1, 624b525a8f0SKuldeep Singh (uint32_t) ((FSPI_RDSR_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) 625b525a8f0SKuldeep Singh | (uint16_t) size)); 626b525a8f0SKuldeep Singh /* Trigger the command */ 627b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); 628b525a8f0SKuldeep Singh /* Wait for command done */ 629b525a8f0SKuldeep Singh while ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK) == 0) 630b525a8f0SKuldeep Singh ; 631b525a8f0SKuldeep Singh fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); 632b525a8f0SKuldeep Singh 633b525a8f0SKuldeep Singh data = fspi_readl(FSPI_RFDR); 634b525a8f0SKuldeep Singh memcpy(rxbuf, &data, size); 635b525a8f0SKuldeep Singh 636b525a8f0SKuldeep Singh /* Rx FIFO invalidation needs to be done prior w1c of INTR.IPRXWA bit */ 637b525a8f0SKuldeep Singh fspi_writel(FSPI_IPRXFCR, FSPI_IPRXFCR_CLR); 638b525a8f0SKuldeep Singh fspi_writel(FSPI_INTR, FSPI_INTR_IPRXWA_MASK); 639b525a8f0SKuldeep Singh fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); 640b525a8f0SKuldeep Singh 641b525a8f0SKuldeep Singh } 642b525a8f0SKuldeep Singh 643b525a8f0SKuldeep Singh bool is_flash_busy(void) 644b525a8f0SKuldeep Singh { 645b525a8f0SKuldeep Singh #define FSPI_ONE_BYTE 1 646b525a8f0SKuldeep Singh uint8_t data[4]; 647b525a8f0SKuldeep Singh 648b525a8f0SKuldeep Singh VERBOSE("In func %s\n\n", __func__); 649b525a8f0SKuldeep Singh fspi_RDSR((uint32_t *) data, 0, FSPI_ONE_BYTE); 650b525a8f0SKuldeep Singh 651b525a8f0SKuldeep Singh return !!((uint32_t) data[0] & FSPI_NOR_SR_WIP_MASK); 652b525a8f0SKuldeep Singh } 653b525a8f0SKuldeep Singh 654b525a8f0SKuldeep Singh int xspi_bulk_erase(void) 655b525a8f0SKuldeep Singh { 656b525a8f0SKuldeep Singh VERBOSE("In func %s\n", __func__); 657b525a8f0SKuldeep Singh xspi_wren((uint32_t) 0x0); 658b525a8f0SKuldeep Singh fspi_bbluk_er(); 659b525a8f0SKuldeep Singh while (is_flash_busy()) 660b525a8f0SKuldeep Singh ; 661b525a8f0SKuldeep Singh fspi_ahb_invalidate(); 662b525a8f0SKuldeep Singh return XSPI_SUCCESS; 663b525a8f0SKuldeep Singh } 664b525a8f0SKuldeep Singh 665b525a8f0SKuldeep Singh static void fspi_sec_er(uint32_t pc_wr_addr) 666b525a8f0SKuldeep Singh { 667b525a8f0SKuldeep Singh uint32_t x_addr; 668b525a8f0SKuldeep Singh 669b525a8f0SKuldeep Singh VERBOSE("In func %s\n", __func__); 670b525a8f0SKuldeep Singh x_addr = (uint32_t)(pc_wr_addr); 671b525a8f0SKuldeep Singh 672b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCR0, x_addr); 673b525a8f0SKuldeep Singh INFO("In [%s][%d] Erase address 0x%x\n", __func__, __LINE__, (x_addr)); 674b525a8f0SKuldeep Singh #if CONFIG_FSPI_ERASE_4K 675b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCR1, ((FSPI_4K_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | 0)); 676b525a8f0SKuldeep Singh #else 677b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCR1, ((FSPI_SE_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | 0)); 678b525a8f0SKuldeep Singh #endif 679b525a8f0SKuldeep Singh fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); 680b525a8f0SKuldeep Singh 681b525a8f0SKuldeep Singh while ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK) == 0) { 682b525a8f0SKuldeep Singh PRA("0x%x", fspi_readl(FSPI_INTR)); 683b525a8f0SKuldeep Singh } 684b525a8f0SKuldeep Singh fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); 685b525a8f0SKuldeep Singh } 686b525a8f0SKuldeep Singh 687b525a8f0SKuldeep Singh int xspi_sector_erase(uint32_t pc_wr_addr, uint32_t ui_len) 688b525a8f0SKuldeep Singh { 689b525a8f0SKuldeep Singh uint32_t x_addr, x_len_bytes, i, num_sector = 0U; 690b525a8f0SKuldeep Singh 691b525a8f0SKuldeep Singh VERBOSE("In func %s\n", __func__); 692b525a8f0SKuldeep Singh x_addr = (uint32_t)(pc_wr_addr); 693b525a8f0SKuldeep Singh if ((x_addr % F_SECTOR_ERASE_SZ) != 0) { 694b525a8f0SKuldeep Singh ERROR("!!! In func %s, unalinged start address can only be in multiples of 0x%x\n", 695b525a8f0SKuldeep Singh __func__, F_SECTOR_ERASE_SZ); 696b525a8f0SKuldeep Singh return -XSPI_ERASE_FAIL; 697b525a8f0SKuldeep Singh } 698b525a8f0SKuldeep Singh 699b525a8f0SKuldeep Singh x_len_bytes = ui_len * 1; 700b525a8f0SKuldeep Singh if (x_len_bytes < F_SECTOR_ERASE_SZ) { 701b525a8f0SKuldeep Singh ERROR("!!! In func %s, Less than 1 sector can only be in multiples of 0x%x\n", 702b525a8f0SKuldeep Singh __func__, F_SECTOR_ERASE_SZ); 703b525a8f0SKuldeep Singh return -XSPI_ERASE_FAIL; 704b525a8f0SKuldeep Singh } 705b525a8f0SKuldeep Singh 706b525a8f0SKuldeep Singh num_sector = x_len_bytes/F_SECTOR_ERASE_SZ; 707b525a8f0SKuldeep Singh num_sector += x_len_bytes % F_SECTOR_ERASE_SZ ? 1U : 0U; 708b525a8f0SKuldeep Singh INFO("F_SECTOR_ERASE_SZ: 0x%08x, num_sector: %d\n", F_SECTOR_ERASE_SZ, num_sector); 709b525a8f0SKuldeep Singh 710b525a8f0SKuldeep Singh for (i = 0U; i < num_sector ; i++) { 711b525a8f0SKuldeep Singh xspi_wren(x_addr + (F_SECTOR_ERASE_SZ * i)); 712b525a8f0SKuldeep Singh fspi_sec_er(x_addr + (F_SECTOR_ERASE_SZ * i)); 713b525a8f0SKuldeep Singh while (is_flash_busy()) 714b525a8f0SKuldeep Singh ; 715b525a8f0SKuldeep Singh } 716b525a8f0SKuldeep Singh fspi_ahb_invalidate(); 717b525a8f0SKuldeep Singh return XSPI_SUCCESS; 718b525a8f0SKuldeep Singh } 719b525a8f0SKuldeep Singh 720b525a8f0SKuldeep Singh 721b525a8f0SKuldeep Singh __attribute__((unused)) static void fspi_delay_ms(uint32_t x) 722b525a8f0SKuldeep Singh { 723b525a8f0SKuldeep Singh volatile unsigned long ul_count; 724b525a8f0SKuldeep Singh 725b525a8f0SKuldeep Singh for (ul_count = 0U; ul_count < (30U * x); ul_count++) 726b525a8f0SKuldeep Singh ; 727b525a8f0SKuldeep Singh 728b525a8f0SKuldeep Singh } 729b525a8f0SKuldeep Singh 730b525a8f0SKuldeep Singh 731b525a8f0SKuldeep Singh #if defined(DEBUG_FLEXSPI) 732b525a8f0SKuldeep Singh static void fspi_dump_regs(void) 733b525a8f0SKuldeep Singh { 734b525a8f0SKuldeep Singh uint32_t i; 735b525a8f0SKuldeep Singh 736b525a8f0SKuldeep Singh VERBOSE("\nRegisters Dump:\n"); 737b525a8f0SKuldeep Singh VERBOSE("Flexspi: Register FSPI_MCR0(0x%x) = 0x%08x\n", FSPI_MCR0, fspi_readl(FSPI_MCR0)); 738b525a8f0SKuldeep Singh VERBOSE("Flexspi: Register FSPI_MCR2(0x%x) = 0x%08x\n", FSPI_MCR2, fspi_readl(FSPI_MCR2)); 739b525a8f0SKuldeep Singh VERBOSE("Flexspi: Register FSPI_DLL_A_CR(0x%x) = 0x%08x\n", FSPI_DLLACR, fspi_readl(FSPI_DLLACR)); 740b525a8f0SKuldeep Singh VERBOSE("\n"); 741b525a8f0SKuldeep Singh 742b525a8f0SKuldeep Singh for (i = 0U; i < 8U; i++) { 743b525a8f0SKuldeep Singh VERBOSE("Flexspi: Register FSPI_AHBRX_BUF0CR0(0x%x) = 0x%08x\n", FSPI_AHBRX_BUF0CR0 + i * 4, fspi_readl((FSPI_AHBRX_BUF0CR0 + i * 4))); 744b525a8f0SKuldeep Singh } 745b525a8f0SKuldeep Singh VERBOSE("\n"); 746b525a8f0SKuldeep Singh 747b525a8f0SKuldeep Singh VERBOSE("Flexspi: Register FSPI_AHBRX_BUF7CR0(0x%x) = 0x%08x\n", FSPI_AHBRX_BUF7CR0, fspi_readl(FSPI_AHBRX_BUF7CR0)); 748b525a8f0SKuldeep Singh VERBOSE("Flexspi: Register FSPI_AHB_CR(0x%x) \t = 0x%08x\n", FSPI_AHBCR, fspi_readl(FSPI_AHBCR)); 749b525a8f0SKuldeep Singh VERBOSE("\n"); 750b525a8f0SKuldeep Singh 751b525a8f0SKuldeep Singh for (i = 0U; i < 4U; i++) { 752b525a8f0SKuldeep Singh VERBOSE("Flexspi: Register FSPI_FLSH_A1_CR2,(0x%x) = 0x%08x\n", FSPI_FLSHA1CR2 + i * 4, fspi_readl(FSPI_FLSHA1CR2 + i * 4)); 753b525a8f0SKuldeep Singh } 754b525a8f0SKuldeep Singh } 755b525a8f0SKuldeep Singh #endif 756b525a8f0SKuldeep Singh 757b525a8f0SKuldeep Singh int fspi_init(uint32_t base_reg_addr, uint32_t flash_start_addr) 758b525a8f0SKuldeep Singh { 759b525a8f0SKuldeep Singh uint32_t mcrx; 760b525a8f0SKuldeep Singh uint32_t flash_size; 761b525a8f0SKuldeep Singh 762b525a8f0SKuldeep Singh if (fspi_base_reg_addr != 0U) { 763b525a8f0SKuldeep Singh INFO("FSPI is already initialized.\n"); 764b525a8f0SKuldeep Singh return XSPI_SUCCESS; 765b525a8f0SKuldeep Singh } 766b525a8f0SKuldeep Singh 767b525a8f0SKuldeep Singh fspi_base_reg_addr = base_reg_addr; 768b525a8f0SKuldeep Singh fspi_flash_base_addr = flash_start_addr; 769b525a8f0SKuldeep Singh 770b525a8f0SKuldeep Singh INFO("Flexspi driver: Version v1.0\n"); 771b525a8f0SKuldeep Singh INFO("Flexspi: Default MCR0 = 0x%08x, before reset\n", fspi_readl(FSPI_MCR0)); 772b525a8f0SKuldeep Singh VERBOSE("Flexspi: Resetting controller...\n"); 773b525a8f0SKuldeep Singh 774b525a8f0SKuldeep Singh /* Reset FlexSpi Controller */ 775b525a8f0SKuldeep Singh fspi_writel(FSPI_MCR0, FSPI_MCR0_SWRST); 776b525a8f0SKuldeep Singh while ((fspi_readl(FSPI_MCR0) & FSPI_MCR0_SWRST)) 777b525a8f0SKuldeep Singh ; /* FSPI_MCR0_SWRESET_MASK */ 778b525a8f0SKuldeep Singh 779b525a8f0SKuldeep Singh 780b525a8f0SKuldeep Singh /* Disable Controller Module before programming its registersi, especially MCR0 (Master Control Register0) */ 781b525a8f0SKuldeep Singh fspi_MDIS(1); 782b525a8f0SKuldeep Singh /* 783b525a8f0SKuldeep Singh * Program MCR0 with default values, AHB Timeout(0xff), IP Timeout(0xff). {FSPI_MCR0- 0xFFFF0000} 784b525a8f0SKuldeep Singh */ 785b525a8f0SKuldeep Singh 786b525a8f0SKuldeep Singh /* Timeout wait cycle for AHB command grant */ 787b525a8f0SKuldeep Singh mcrx = fspi_readl(FSPI_MCR0); 788b525a8f0SKuldeep Singh mcrx |= (uint32_t)((FSPI_MAX_TIMEOUT_AHBCMD << FSPI_MCR0_AHBGRANTWAIT_SHIFT) & (FSPI_MCR0_AHBGRANTWAIT_MASK)); 789b525a8f0SKuldeep Singh 790b525a8f0SKuldeep Singh /* Time out wait cycle for IP command grant*/ 791b525a8f0SKuldeep Singh mcrx |= (uint32_t) (FSPI_MAX_TIMEOUT_IPCMD << FSPI_MCR0_IPGRANTWAIT_SHIFT) & (FSPI_MCR0_IPGRANTWAIT_MASK); 792b525a8f0SKuldeep Singh 793b525a8f0SKuldeep Singh /* TODO why BE64 set BE32*/ 794b525a8f0SKuldeep Singh mcrx |= (uint32_t) (FSPI_ENDCFG_LE64 << FSPI_MCR0_ENDCFG_SHIFT) & FSPI_MCR0_ENDCFG_MASK; 795b525a8f0SKuldeep Singh 796b525a8f0SKuldeep Singh fspi_writel(FSPI_MCR0, mcrx); 797b525a8f0SKuldeep Singh 798b525a8f0SKuldeep Singh /* Reset the DLL register to default value */ 799b525a8f0SKuldeep Singh fspi_writel(FSPI_DLLACR, FSPI_DLLACR_OVRDEN); 800b525a8f0SKuldeep Singh fspi_writel(FSPI_DLLBCR, FSPI_DLLBCR_OVRDEN); 801b525a8f0SKuldeep Singh 802b525a8f0SKuldeep Singh #if ERRATA_FLASH_A050272 /* ERRATA DLL */ 803b525a8f0SKuldeep Singh for (uint8_t delay = 100U; delay > 0U; delay--) { 804b525a8f0SKuldeep Singh __asm__ volatile ("nop"); 805b525a8f0SKuldeep Singh } 806b525a8f0SKuldeep Singh #endif 807b525a8f0SKuldeep Singh 808b525a8f0SKuldeep Singh /* Configure flash control registers for different chip select */ 809b525a8f0SKuldeep Singh flash_size = (F_FLASH_SIZE_BYTES * FLASH_NUM) / FSPI_BYTES_PER_KBYTES; 810b525a8f0SKuldeep Singh fspi_writel(FSPI_FLSHA1CR0, flash_size); 811b525a8f0SKuldeep Singh fspi_writel(FSPI_FLSHA2CR0, 0U); 812b525a8f0SKuldeep Singh fspi_writel(FSPI_FLSHB1CR0, 0U); 813b525a8f0SKuldeep Singh fspi_writel(FSPI_FLSHB2CR0, 0U); 814b525a8f0SKuldeep Singh 815b525a8f0SKuldeep Singh #if defined(CONFIG_FSPI_AHB) 816b525a8f0SKuldeep Singh fspi_init_ahb(); 817b525a8f0SKuldeep Singh #endif 818b525a8f0SKuldeep Singh /* RE-Enable Controller Module */ 819b525a8f0SKuldeep Singh fspi_MDIS(0); 820b525a8f0SKuldeep Singh INFO("Flexspi: After MCR0 = 0x%08x,\n", fspi_readl(FSPI_MCR0)); 821b525a8f0SKuldeep Singh fspi_setup_LUT(); 822b525a8f0SKuldeep Singh 823b525a8f0SKuldeep Singh /* Dump of all registers, ensure controller not disabled anymore*/ 824b525a8f0SKuldeep Singh #if defined(DEBUG_FLEXSPI) 825b525a8f0SKuldeep Singh fspi_dump_regs(); 826b525a8f0SKuldeep Singh #endif 827b525a8f0SKuldeep Singh 828b525a8f0SKuldeep Singh INFO("Flexspi: Init done!!\n"); 829b525a8f0SKuldeep Singh 830b525a8f0SKuldeep Singh #if DEBUG_FLEXSPI 831b525a8f0SKuldeep Singh 832b525a8f0SKuldeep Singh uint32_t xspi_addr = SZ_57M; 833b525a8f0SKuldeep Singh 834b525a8f0SKuldeep Singh /* 835b525a8f0SKuldeep Singh * Second argument of fspi_test is the size of buffer(s) passed 836b525a8f0SKuldeep Singh * to the function. 837b525a8f0SKuldeep Singh * SIZE_BUFFER defined in test_fspi.c is kept large enough to 838b525a8f0SKuldeep Singh * accommodate variety of sizes for regressive tests. 839b525a8f0SKuldeep Singh */ 840b525a8f0SKuldeep Singh fspi_test(xspi_addr, 0x40, 0); 841b525a8f0SKuldeep Singh fspi_test(xspi_addr, 0x15, 2); 842b525a8f0SKuldeep Singh fspi_test(xspi_addr, 0x80, 0); 843b525a8f0SKuldeep Singh fspi_test(xspi_addr, 0x81, 0); 844b525a8f0SKuldeep Singh fspi_test(xspi_addr, 0x79, 3); 845b525a8f0SKuldeep Singh 846b525a8f0SKuldeep Singh fspi_test(xspi_addr + 0x11, 0x15, 0); 847b525a8f0SKuldeep Singh fspi_test(xspi_addr + 0x11, 0x40, 0); 848b525a8f0SKuldeep Singh fspi_test(xspi_addr + 0xff, 0x40, 1); 849b525a8f0SKuldeep Singh fspi_test(xspi_addr + 0x25, 0x81, 2); 850b525a8f0SKuldeep Singh fspi_test(xspi_addr + 0xef, 0x6f, 3); 851b525a8f0SKuldeep Singh 852b525a8f0SKuldeep Singh fspi_test((xspi_addr - F_SECTOR_ERASE_SZ), 0x229, 0); 853b525a8f0SKuldeep Singh #endif 854b525a8f0SKuldeep Singh 855b525a8f0SKuldeep Singh return XSPI_SUCCESS; 856b525a8f0SKuldeep Singh } 857