@@ -1462,7 +1462,7 @@ static int m25p80_cs(SSIPeripheral *ss, bool select)
return 0;
}
-static uint32_t m25p80_transfer8(SSIPeripheral *ss, uint32_t tx)
+static uint32_t m25p80_transfer8_ex(SSIPeripheral *ss, uint32_t tx)
{
Flash *s = M25P80(ss);
uint32_t r = 0;
@@ -1548,6 +1548,33 @@ static uint32_t m25p80_transfer8(SSIPeripheral *ss, uint32_t tx)
return r;
}
+/*
+ * Pre-reading logic for m25p80_transfer8:
+ * The existing SPI model assumes the output byte is fully formed,
+ * can be passed to the SPI device, and the input byte can be returned,
+ * all in one operation. With SPI-GPIO, we don't have the input byte
+ * until all 8 bits of the output have been shifted out, so we have
+ * to prime the MISO with bogus values (0xFF).
+ */
+static uint32_t m25p80_transfer8(SSIPeripheral *ss, uint32_t tx)
+{
+ Flash *s = M25P80(ss);
+ SSIBus *ssibus = (SSIBus *)qdev_get_parent_bus(DEVICE(s));
+
+ uint8_t prev_state = s->state;
+ uint32_t r = m25p80_transfer8_ex(ss, tx);
+ uint8_t curr_state = s->state;
+
+ if (ssibus->preread &&
+ /* cmd state has changed into DATA reading state */
+ (!(prev_state == STATE_READ || prev_state == STATE_READING_DATA) &&
+ (curr_state == STATE_READ || curr_state == STATE_READING_DATA))) {
+ r = m25p80_transfer8_ex(ss, 0xFF);
+ }
+
+ return r;
+}
+
static void m25p80_write_protect_pin_irq_handler(void *opaque, int n, int level)
{
Flash *s = M25P80(opaque);
@@ -19,10 +19,6 @@
#include "qapi/error.h"
#include "qom/object.h"
-struct SSIBus {
- BusState parent_obj;
-};
-
#define TYPE_SSI_BUS "SSI"
OBJECT_DECLARE_SIMPLE_TYPE(SSIBus, SSI_BUS)
@@ -30,6 +30,11 @@ enum SSICSMode {
SSI_CS_HIGH,
};
+struct SSIBus {
+ BusState parent_obj;
+ bool preread;
+};
+
/* Peripherals. */
struct SSIPeripheralClass {
DeviceClass parent_class;
With SPI-GPIO we don't have the input bits until all 8 bits of the output have been shifted out, so we have to prime the MISO with bogus values (0xFF). Signed-off-by: Iris Chen <irischenlj@fb.com> --- hw/block/m25p80.c | 29 ++++++++++++++++++++++++++++- hw/ssi/ssi.c | 4 ---- include/hw/ssi/ssi.h | 5 +++++ 3 files changed, 33 insertions(+), 5 deletions(-)