dm: Convert spi_flash_probe() and 'sf probe' to use driver model

We want the SPI flash probing feature to operate as a standard driver.
Add a driver for the basic probing feature used by most boards. This
will be activated by device_probe() as with any other driver.

The 'sf probe' command currently keeps track of the SPI slave that it
last used. This doesn't work with driver model, since some other driver
or system may have probed the device and have access to it too. On the
other hand, if we try to probe a device twice the second probe is a nop
with driver model.

Fix this by searching for the matching device, removing it, and then
probing it again. This should work as expected regardless of other device
activity.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Jagannadha Sutradharudu Teki <jagannadh.teki@gmail.com>
This commit is contained in:
Simon Glass 2014-10-13 23:42:07 -06:00
parent 4c2dbefde5
commit fbb099183e
2 changed files with 89 additions and 2 deletions

View File

@ -8,11 +8,13 @@
#include <common.h>
#include <div64.h>
#include <dm.h>
#include <malloc.h>
#include <spi.h>
#include <spi_flash.h>
#include <asm/io.h>
#include <dm/device-internal.h>
static struct spi_flash *flash;
@ -81,7 +83,12 @@ static int do_spi_flash_probe(int argc, char * const argv[])
unsigned int speed = CONFIG_SF_DEFAULT_SPEED;
unsigned int mode = CONFIG_SF_DEFAULT_MODE;
char *endp;
#ifdef CONFIG_DM_SPI_FLASH
struct udevice *new, *bus_dev;
int ret;
#else
struct spi_flash *new;
#endif
if (argc >= 2) {
cs = simple_strtoul(argv[1], &endp, 0);
@ -109,6 +116,23 @@ static int do_spi_flash_probe(int argc, char * const argv[])
return -1;
}
#ifdef CONFIG_DM_SPI_FLASH
/* Remove the old device, otherwise probe will just be a nop */
ret = spi_find_bus_and_cs(bus, cs, &bus_dev, &new);
if (!ret) {
device_remove(new);
device_unbind(new);
}
flash = NULL;
ret = spi_flash_probe_bus_cs(bus, cs, speed, mode, &new);
if (ret) {
printf("Failed to initialize SPI flash at %u:%u (error %d)\n",
bus, cs, ret);
return 1;
}
flash = new->uclass_priv;
#else
new = spi_flash_probe(bus, cs, speed, mode);
if (!new) {
printf("Failed to initialize SPI flash at %u:%u\n", bus, cs);
@ -118,6 +142,7 @@ static int do_spi_flash_probe(int argc, char * const argv[])
if (flash)
spi_flash_free(flash);
flash = new;
#endif
return 0;
}

View File

@ -9,6 +9,7 @@
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
#include <malloc.h>
@ -131,13 +132,15 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
flash->dual_flash = flash->spi->option;
/* Assign spi_flash ops */
#ifndef CONFIG_DM_SPI_FLASH
flash->write = spi_flash_cmd_write_ops;
#ifdef CONFIG_SPI_FLASH_SST
#if defined(CONFIG_SPI_FLASH_SST)
if (params->flags & SST_WP)
flash->write = sst_write_wp;
#endif
flash->erase = spi_flash_cmd_erase_ops;
flash->read = spi_flash_cmd_read_ops;
#endif
/* Compute the flash size */
flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0;
@ -398,7 +401,8 @@ err_read_id:
return ret;
}
static struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus)
#ifndef CONFIG_DM_SPI_FLASH
struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus)
{
struct spi_flash *flash;
@ -443,3 +447,61 @@ void spi_flash_free(struct spi_flash *flash)
spi_free_slave(flash->spi);
free(flash);
}
#else /* defined CONFIG_DM_SPI_FLASH */
static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len,
void *buf)
{
struct spi_flash *flash = dev->uclass_priv;
return spi_flash_cmd_read_ops(flash, offset, len, buf);
}
int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len,
const void *buf)
{
struct spi_flash *flash = dev->uclass_priv;
return spi_flash_cmd_write_ops(flash, offset, len, buf);
}
int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
{
struct spi_flash *flash = dev->uclass_priv;
return spi_flash_cmd_erase_ops(flash, offset, len);
}
int spi_flash_std_probe(struct udevice *dev)
{
struct spi_slave *slave = dev_get_parentdata(dev);
struct spi_flash *flash;
flash = dev->uclass_priv;
flash->dev = dev;
debug("%s: slave=%p, cs=%d\n", __func__, slave, slave->cs);
return spi_flash_probe_slave(slave, flash);
}
static const struct dm_spi_flash_ops spi_flash_std_ops = {
.read = spi_flash_std_read,
.write = spi_flash_std_write,
.erase = spi_flash_std_erase,
};
static const struct udevice_id spi_flash_std_ids[] = {
{ .compatible = "spi-flash" },
{ }
};
U_BOOT_DRIVER(spi_flash_std) = {
.name = "spi_flash_std",
.id = UCLASS_SPI_FLASH,
.of_match = spi_flash_std_ids,
.probe = spi_flash_std_probe,
.priv_auto_alloc_size = sizeof(struct spi_flash),
.ops = &spi_flash_std_ops,
};
#endif /* CONFIG_DM_SPI_FLASH */