Esempio n. 1
0
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);
}
Esempio n. 2
0
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;
}