Esempio n. 1
0
/**
 * spi_flash_probe_slave() - Probe for a SPI flash device on a bus
 *
 * @flashp: Pointer to place to put flash info, which may be NULL if the
 * space should be allocated
 */
static int spi_flash_probe_slave(struct spi_flash *flash)
{
	struct spi_slave *spi = flash->spi;
	int ret;

	/* Setup spi_slave */
	if (!spi) {
		printf("SF: Failed to set up slave\n");
		return -ENODEV;
	}

	/* Claim spi bus */
	ret = spi_claim_bus(spi);
	if (ret) {
		debug("SF: Failed to claim SPI bus: %d\n", ret);
		return ret;
	}

	ret = spi_nor_scan(flash);
	if (ret)
		goto err_read_id;

#ifdef CONFIG_SPI_FLASH_MTD
	ret = spi_flash_mtd_register(flash);
#endif

err_read_id:
	spi_release_bus(spi);
	return ret;
}
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;
}