void SPIFI_Init(SPIFI_Type *base, const spifi_config_t *config) { assert(config); #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the SAI clock */ CLOCK_EnableClock(s_spifiClock[SPIFI_GetInstance(base)]); #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Reset the Command register */ SPIFI_ResetCommand(base); /* Set time delay parameter */ base->CTRL = SPIFI_CTRL_TIMEOUT(config->timeout) | SPIFI_CTRL_CSHIGH(config->csHighTime) | SPIFI_CTRL_D_PRFTCH_DIS(config->disablePrefetch) | SPIFI_CTRL_MODE3(config->spiMode) | SPIFI_CTRL_PRFTCH_DIS(config->disableCachePrefech) | SPIFI_CTRL_DUAL(config->dualMode) | SPIFI_CTRL_RFCLK(config->isReadFullClockCycle) | SPIFI_CTRL_FBCLK(config->isFeedbackClock); }
static int nxp_spifi_setup_flash(struct nxp_spifi *spifi, struct device_node *np) { struct mtd_part_parser_data ppdata; enum read_mode flash_read; u32 ctrl, property; u16 mode = 0; int ret; if (!of_property_read_u32(np, "spi-rx-bus-width", &property)) { switch (property) { case 1: break; case 2: mode |= SPI_RX_DUAL; break; case 4: mode |= SPI_RX_QUAD; break; default: dev_err(spifi->dev, "unsupported rx-bus-width\n"); return -EINVAL; } } if (of_find_property(np, "spi-cpha", NULL)) mode |= SPI_CPHA; if (of_find_property(np, "spi-cpol", NULL)) mode |= SPI_CPOL; /* Setup control register defaults */ ctrl = SPIFI_CTRL_TIMEOUT(1000) | SPIFI_CTRL_CSHIGH(15) | SPIFI_CTRL_FBCLK; if (mode & SPI_RX_DUAL) { ctrl |= SPIFI_CTRL_DUAL; flash_read = SPI_NOR_DUAL; } else if (mode & SPI_RX_QUAD) { ctrl &= ~SPIFI_CTRL_DUAL; flash_read = SPI_NOR_QUAD; } else { ctrl |= SPIFI_CTRL_DUAL; flash_read = SPI_NOR_NORMAL; } switch (mode & (SPI_CPHA | SPI_CPOL)) { case SPI_MODE_0: ctrl &= ~SPIFI_CTRL_MODE3; break; case SPI_MODE_3: ctrl |= SPIFI_CTRL_MODE3; break; default: dev_err(spifi->dev, "only mode 0 and 3 supported\n"); return -EINVAL; } writel(ctrl, spifi->io_base + SPIFI_CTRL); spifi->mtd.priv = &spifi->nor; spifi->nor.mtd = &spifi->mtd; spifi->nor.dev = spifi->dev; spifi->nor.priv = spifi; spifi->nor.read = nxp_spifi_read; spifi->nor.write = nxp_spifi_write; spifi->nor.erase = nxp_spifi_erase; spifi->nor.read_reg = nxp_spifi_read_reg; spifi->nor.write_reg = nxp_spifi_write_reg; /* * The first read on a hard reset isn't reliable so do a * dummy read of the id before calling spi_nor_scan(). * The reason for this problem is unknown. * * The official NXP spifilib uses more or less the same * workaround that is applied here by reading the device * id multiple times. */ nxp_spifi_dummy_id_read(&spifi->nor); ret = spi_nor_scan(&spifi->nor, NULL, flash_read); if (ret) { dev_err(spifi->dev, "device scan failed\n"); return ret; } ret = nxp_spifi_setup_memory_cmd(spifi); if (ret) { dev_err(spifi->dev, "memory command setup failed\n"); return ret; } ppdata.of_node = np; ret = mtd_device_parse_register(&spifi->mtd, NULL, &ppdata, NULL, 0); if (ret) { dev_err(spifi->dev, "mtd device parse failed\n"); return ret; } return 0; }