On Thu, Jun 27, 2019 at 2:09 PM Philippe Mathieu-Daudé <phi...@redhat.com> wrote: > > From: Stephen Checkoway <stephen.checko...@oberlin.edu> > > After a flash device enters CFI mode from autoselect mode, the reset > command returns the device to autoselect mode. An additional reset > command is necessary to return to read array mode. > > Signed-off-by: Stephen Checkoway <stephen.checko...@oberlin.edu> > Acked-by: Thomas Huth <th...@redhat.com> > Message-Id: <20190426162624.55977-7-stephen.checko...@oberlin.edu> > Signed-off-by: Philippe Mathieu-Daudé <phi...@redhat.com>
Acked-by: Alistair Francis <alistair.fran...@wdc.com> Alistair > --- > hw/block/pflash_cfi02.c | 22 ++++++++++++++++++---- > tests/pflash-cfi02-test.c | 39 +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 57 insertions(+), 4 deletions(-) > > diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c > index 08b2bc83cb..13f76fa71d 100644 > --- a/hw/block/pflash_cfi02.c > +++ b/hw/block/pflash_cfi02.c > @@ -66,6 +66,7 @@ do { \ > /* Special write cycles for CFI queries. */ > enum { > WCYCLE_CFI = 7, > + WCYCLE_AUTOSELECT_CFI = 8, > }; > > struct PFlashCFI02 { > @@ -311,6 +312,12 @@ static void pflash_write(void *opaque, hwaddr offset, > uint64_t value, > cmd = value; > if (pfl->cmd != 0xA0) { > if (cmd == 0xF0) { > + if (pfl->wcycle == WCYCLE_AUTOSELECT_CFI) { > + /* Return to autoselect mode. */ > + pfl->wcycle = 3; > + pfl->cmd = 0x90; > + return; > + } > goto reset_flash; > } > } > @@ -333,7 +340,6 @@ static void pflash_write(void *opaque, hwaddr offset, > uint64_t value, > /* We're in read mode */ > check_unlock0: > if (boff == 0x55 && cmd == 0x98) { > - enter_CFI_mode: > /* Enter CFI query mode */ > pfl->wcycle = WCYCLE_CFI; > pfl->cmd = 0x98; > @@ -410,9 +416,16 @@ static void pflash_write(void *opaque, hwaddr offset, > uint64_t value, > /* Unlock bypass reset */ > goto reset_flash; > } > - /* We can enter CFI query mode from autoselect mode */ > - if (boff == 0x55 && cmd == 0x98) > - goto enter_CFI_mode; > + /* > + * We can enter CFI query mode from autoselect mode, but we must > + * return to autoselect mode after a reset. > + */ > + if (boff == 0x55 && cmd == 0x98) { > + /* Enter autoselect CFI query mode */ > + pfl->wcycle = WCYCLE_AUTOSELECT_CFI; > + pfl->cmd = 0x98; > + return; > + } > /* No break here */ > default: > DPRINTF("%s: invalid write for command %02x\n", > @@ -493,6 +506,7 @@ static void pflash_write(void *opaque, hwaddr offset, > uint64_t value, > break; > /* Special values for CFI queries */ > case WCYCLE_CFI: > + case WCYCLE_AUTOSELECT_CFI: > DPRINTF("%s: invalid write in CFI query mode\n", __func__); > goto reset_flash; > default: > diff --git a/tests/pflash-cfi02-test.c b/tests/pflash-cfi02-test.c > index 1659eaebce..00e2261742 100644 > --- a/tests/pflash-cfi02-test.c > +++ b/tests/pflash-cfi02-test.c > @@ -407,6 +407,42 @@ static void test_geometry(const void *opaque) > qtest_quit(qtest); > } > > +/* > + * Test that > + * 1. enter autoselect mode; > + * 2. enter CFI mode; and then > + * 3. exit CFI mode > + * leaves the flash device in autoselect mode. > + */ > +static void test_cfi_in_autoselect(const void *opaque) > +{ > + const FlashConfig *config = opaque; > + QTestState *qtest; > + qtest = qtest_initf("-M musicpal,accel=qtest" > + " -drive if=pflash,file=%s,format=raw,copy-on-read", > + image_path); > + FlashConfig explicit_config = expand_config_defaults(config); > + explicit_config.qtest = qtest; > + const FlashConfig *c = &explicit_config; > + > + /* 1. Enter autoselect. */ > + unlock(c); > + flash_cmd(c, UNLOCK0_ADDR, AUTOSELECT_CMD); > + g_assert_cmpint(flash_query(c, FLASH_ADDR(0)), ==, replicate(c, 0xBF)); > + > + /* 2. Enter CFI. */ > + flash_cmd(c, CFI_ADDR, CFI_CMD); > + g_assert_cmpint(flash_query(c, FLASH_ADDR(0x10)), ==, replicate(c, 'Q')); > + g_assert_cmpint(flash_query(c, FLASH_ADDR(0x11)), ==, replicate(c, 'R')); > + g_assert_cmpint(flash_query(c, FLASH_ADDR(0x12)), ==, replicate(c, 'Y')); > + > + /* 3. Exit CFI. */ > + reset(c); > + g_assert_cmpint(flash_query(c, FLASH_ADDR(0)), ==, replicate(c, 0xBF)); > + > + qtest_quit(qtest); > +} > + > static void cleanup(void *opaque) > { > unlink(image_path); > @@ -474,6 +510,9 @@ int main(int argc, char **argv) > qtest_add_data_func(path, config, test_geometry); > g_free(path); > } > + > + qtest_add_data_func("pflash-cfi02/cfi-in-autoselect", &configuration[0], > + test_cfi_in_autoselect); > int result = g_test_run(); > cleanup(NULL); > return result; > -- > 2.20.1 > >