/** * 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; }
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; }