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