UPSTREAM: sf: Add a method to obtain the block-protect setting
It is useful to obtain the block-protect setting of the SPI flash, so we know whether it is fully open or (perhaps partially) write-protected. Add a method for this. Update the sandbox driver to process this operation and add a test. Signed-off-by: Simon Glass <sjg@chromium.org Change-Id: I8e8abe197ab483a26622f02666cc234a1544e642 Signed-off-by: Jon Lin <jon.lin@rock-chips.com> (cherry picked from commit a58986ca8b53d8c7a441397082f84edc7f47d19f)
This commit is contained in:
parent
59beb0b0a8
commit
b6e92505d5
|
|
@ -79,4 +79,35 @@ long sandbox_i2c_rtc_get_set_base_time(struct udevice *dev, long base_time);
|
||||||
|
|
||||||
int sandbox_usb_keyb_add_string(struct udevice *dev, const char *str);
|
int sandbox_usb_keyb_add_string(struct udevice *dev, const char *str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sandbox_osd_get_mem() - get the internal memory of a sandbox OSD
|
||||||
|
*
|
||||||
|
* @dev: OSD device for which to access the internal memory for
|
||||||
|
* @buf: pointer to buffer to receive the OSD memory data
|
||||||
|
* @buflen: length of buffer in bytes
|
||||||
|
*/
|
||||||
|
int sandbox_osd_get_mem(struct udevice *dev, u8 *buf, size_t buflen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sandbox_pwm_get_config() - get the PWM config for a channel
|
||||||
|
*
|
||||||
|
* @dev: Device to check
|
||||||
|
* @channel: Channel number to check
|
||||||
|
* @period_ns: Period of the PWM in nanoseconds
|
||||||
|
* @duty_ns: Current duty cycle of the PWM in nanoseconds
|
||||||
|
* @enable: true if the PWM is enabled
|
||||||
|
* @polarity: true if the PWM polarity is active high
|
||||||
|
* @return 0 if OK, -ENOSPC if the PWM number is invalid
|
||||||
|
*/
|
||||||
|
int sandbox_pwm_get_config(struct udevice *dev, uint channel, uint *period_nsp,
|
||||||
|
uint *duty_nsp, bool *enablep, bool *polarityp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sandbox_sf_set_block_protect() - Set the BP bits of the status register
|
||||||
|
*
|
||||||
|
* @dev: Device to update
|
||||||
|
* @bp_mask: BP bits to set (bits 2:0, so a value of 0 to 7)
|
||||||
|
*/
|
||||||
|
void sandbox_sf_set_block_protect(struct udevice *dev, int bp_mask);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,8 @@ static const char *sandbox_sf_state_name(enum sandbox_sf_state state)
|
||||||
/* Bits for the status register */
|
/* Bits for the status register */
|
||||||
#define STAT_WIP (1 << 0)
|
#define STAT_WIP (1 << 0)
|
||||||
#define STAT_WEL (1 << 1)
|
#define STAT_WEL (1 << 1)
|
||||||
|
#define STAT_BP_SHIFT 2
|
||||||
|
#define STAT_BP_MASK (7 << STAT_BP_SHIFT)
|
||||||
|
|
||||||
/* Assume all SPI flashes have 3 byte addresses since they do atm */
|
/* Assume all SPI flashes have 3 byte addresses since they do atm */
|
||||||
#define SF_ADDR_LEN 3
|
#define SF_ADDR_LEN 3
|
||||||
|
|
@ -104,6 +106,14 @@ struct sandbox_spi_flash_plat_data {
|
||||||
int cs;
|
int cs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void sandbox_sf_set_block_protect(struct udevice *dev, int bp_mask)
|
||||||
|
{
|
||||||
|
struct sandbox_spi_flash *sbsf = dev_get_priv(dev);
|
||||||
|
|
||||||
|
sbsf->status &= ~STAT_BP_MASK;
|
||||||
|
sbsf->status |= bp_mask << STAT_BP_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a very strange probe function. If it has platform data (which may
|
* This is a very strange probe function. If it has platform data (which may
|
||||||
* have come from the device tree) then this function gets the filename and
|
* have come from the device tree) then this function gets the filename and
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,15 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len)
|
||||||
return log_ret(sf_get_ops(dev)->erase(dev, offset, len));
|
return log_ret(sf_get_ops(dev)->erase(dev, offset, len));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int spl_flash_get_sw_write_prot(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct dm_spi_flash_ops *ops = sf_get_ops(dev);
|
||||||
|
|
||||||
|
if (!ops->get_sw_write_prot)
|
||||||
|
return -ENOSYS;
|
||||||
|
return log_ret(ops->get_sw_write_prot(dev));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO(sjg@chromium.org): This is an old-style function. We should remove
|
* TODO(sjg@chromium.org): This is an old-style function. We should remove
|
||||||
* it when all SPI flash drivers use dm
|
* it when all SPI flash drivers use dm
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,9 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
|
||||||
/* Flash erase(sectors) operation, support all possible erase commands */
|
/* Flash erase(sectors) operation, support all possible erase commands */
|
||||||
int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len);
|
int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len);
|
||||||
|
|
||||||
|
/* Get software write-protect value (BP bits) */
|
||||||
|
int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash);
|
||||||
|
|
||||||
/* Lock stmicro spi flash region */
|
/* Lock stmicro spi flash region */
|
||||||
int stm_lock(struct spi_flash *flash, u32 ofs, size_t len);
|
int stm_lock(struct spi_flash *flash, u32 ofs, size_t len);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,13 @@ static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
|
||||||
return spi_flash_cmd_erase_ops(flash, offset, len);
|
return spi_flash_cmd_erase_ops(flash, offset, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int spi_flash_std_get_sw_write_prot(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct spi_flash *flash = dev_get_uclass_priv(dev);
|
||||||
|
|
||||||
|
return spi_flash_cmd_get_sw_write_prot(flash);
|
||||||
|
}
|
||||||
|
|
||||||
static int spi_flash_std_probe(struct udevice *dev)
|
static int spi_flash_std_probe(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct spi_slave *slave = dev_get_parent_priv(dev);
|
struct spi_slave *slave = dev_get_parent_priv(dev);
|
||||||
|
|
@ -142,6 +149,7 @@ static const struct dm_spi_flash_ops spi_flash_std_ops = {
|
||||||
.read = spi_flash_std_read,
|
.read = spi_flash_std_read,
|
||||||
.write = spi_flash_std_write,
|
.write = spi_flash_std_write,
|
||||||
.erase = spi_flash_std_erase,
|
.erase = spi_flash_std_erase,
|
||||||
|
.get_sw_write_prot = spi_flash_std_get_sw_write_prot,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct udevice_id spi_flash_std_ids[] = {
|
static const struct udevice_id spi_flash_std_ids[] = {
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,18 @@ static int write_cr(struct spi_flash *flash, u8 wc)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash)
|
||||||
|
{
|
||||||
|
u8 status;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = read_sr(flash, &status);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return (status >> 2) & 7;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SPI_FLASH_BAR
|
#ifdef CONFIG_SPI_FLASH_BAR
|
||||||
/*
|
/*
|
||||||
* This "clean_bar" is necessary in a situation when one was accessing
|
* This "clean_bar" is necessary in a situation when one was accessing
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,19 @@ struct dm_spi_flash_ops {
|
||||||
int (*write)(struct udevice *dev, u32 offset, size_t len,
|
int (*write)(struct udevice *dev, u32 offset, size_t len,
|
||||||
const void *buf);
|
const void *buf);
|
||||||
int (*erase)(struct udevice *dev, u32 offset, size_t len);
|
int (*erase)(struct udevice *dev, u32 offset, size_t len);
|
||||||
|
/**
|
||||||
|
* get_sw_write_prot() - Check state of software write-protect feature
|
||||||
|
*
|
||||||
|
* SPI flash chips can lock a region of the flash defined by a
|
||||||
|
* 'protected area'. This function checks if this protected area is
|
||||||
|
* defined.
|
||||||
|
*
|
||||||
|
* @dev: SPI flash device
|
||||||
|
* @return 0 if no region is write-protected, 1 if a region is
|
||||||
|
* write-protected, -ENOSYS if the driver does not implement this,
|
||||||
|
* other -ve value on error
|
||||||
|
*/
|
||||||
|
int (*get_sw_write_prot)(struct udevice *dev);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Access the serial operations for a device */
|
/* Access the serial operations for a device */
|
||||||
|
|
@ -154,6 +167,20 @@ int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len,
|
||||||
*/
|
*/
|
||||||
int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len);
|
int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* spl_flash_get_sw_write_prot() - Check state of software write-protect feature
|
||||||
|
*
|
||||||
|
* SPI flash chips can lock a region of the flash defined by a
|
||||||
|
* 'protected area'. This function checks if this protected area is
|
||||||
|
* defined.
|
||||||
|
*
|
||||||
|
* @dev: SPI flash device
|
||||||
|
* @return 0 if no region is write-protected, 1 if a region is
|
||||||
|
* write-protected, -ENOSYS if the driver does not implement this,
|
||||||
|
* other -ve value on error
|
||||||
|
*/
|
||||||
|
int spl_flash_get_sw_write_prot(struct udevice *dev);
|
||||||
|
|
||||||
int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
|
int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
|
||||||
unsigned int max_hz, unsigned int spi_mode,
|
unsigned int max_hz, unsigned int spi_mode,
|
||||||
struct udevice **devp);
|
struct udevice **devp);
|
||||||
|
|
|
||||||
49
test/dm/sf.c
49
test/dm/sf.c
|
|
@ -10,12 +10,61 @@
|
||||||
#include <spi.h>
|
#include <spi.h>
|
||||||
#include <spi_flash.h>
|
#include <spi_flash.h>
|
||||||
#include <asm/state.h>
|
#include <asm/state.h>
|
||||||
|
#include <asm/test.h>
|
||||||
#include <dm/test.h>
|
#include <dm/test.h>
|
||||||
#include <dm/util.h>
|
#include <dm/util.h>
|
||||||
#include <test/ut.h>
|
#include <test/ut.h>
|
||||||
|
|
||||||
/* Test that sandbox SPI flash works correctly */
|
/* Test that sandbox SPI flash works correctly */
|
||||||
static int dm_test_spi_flash(struct unit_test_state *uts)
|
static int dm_test_spi_flash(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
struct udevice *dev, *emul;
|
||||||
|
int full_size = 0x200000;
|
||||||
|
int size = 0x10000;
|
||||||
|
u8 *src, *dst;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
src = map_sysmem(0x20000, full_size);
|
||||||
|
ut_assertok(os_write_file("spi.bin", src, full_size));
|
||||||
|
ut_assertok(uclass_first_device_err(UCLASS_SPI_FLASH, &dev));
|
||||||
|
|
||||||
|
dst = map_sysmem(0x20000 + full_size, full_size);
|
||||||
|
ut_assertok(spi_flash_read_dm(dev, 0, size, dst));
|
||||||
|
ut_assertok(memcmp(src, dst, size));
|
||||||
|
|
||||||
|
/* Erase */
|
||||||
|
ut_assertok(spi_flash_erase_dm(dev, 0, size));
|
||||||
|
ut_assertok(spi_flash_read_dm(dev, 0, size, dst));
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
ut_asserteq(dst[i], 0xff);
|
||||||
|
|
||||||
|
/* Write some new data */
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
src[i] = i;
|
||||||
|
ut_assertok(spi_flash_write_dm(dev, 0, size, src));
|
||||||
|
ut_assertok(spi_flash_read_dm(dev, 0, size, dst));
|
||||||
|
ut_assertok(memcmp(src, dst, size));
|
||||||
|
|
||||||
|
/* Try the write-protect stuff */
|
||||||
|
ut_assertok(uclass_first_device_err(UCLASS_SPI_EMUL, &emul));
|
||||||
|
ut_asserteq(0, spl_flash_get_sw_write_prot(dev));
|
||||||
|
sandbox_sf_set_block_protect(emul, 1);
|
||||||
|
ut_asserteq(1, spl_flash_get_sw_write_prot(dev));
|
||||||
|
sandbox_sf_set_block_protect(emul, 0);
|
||||||
|
ut_asserteq(0, spl_flash_get_sw_write_prot(dev));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since we are about to destroy all devices, we must tell sandbox
|
||||||
|
* to forget the emulation device
|
||||||
|
*/
|
||||||
|
sandbox_sf_unbind_emul(state_get_current(), 0, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DM_TEST(dm_test_spi_flash, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
||||||
|
|
||||||
|
/* Functional test that sandbox SPI flash works correctly */
|
||||||
|
static int dm_test_spi_flash_func(struct unit_test_state *uts)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Create an empty test file and run the SPI flash tests. This is a
|
* Create an empty test file and run the SPI flash tests. This is a
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue